Optimise users home page
This commit is contained in:
parent
638472fb4f
commit
bac4fd6227
@ -102,20 +102,6 @@ class HomeController extends Controller
|
|||||||
return $this->invoice_pdf($o);
|
return $this->invoice_pdf($o);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper to redirect to the old site, when functions are not available in this one.
|
|
||||||
*
|
|
||||||
* @param $type
|
|
||||||
* @param $action
|
|
||||||
* @param $id
|
|
||||||
* @return void
|
|
||||||
* @deprecated @todo Remove once all functions added
|
|
||||||
*/
|
|
||||||
public function oldsite($type,$action,$id)
|
|
||||||
{
|
|
||||||
abort(307,sprintf('http://www.graytech.net.au/u/%s/%s/%s',$type,$action,$id));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return details on the users service
|
* Return details on the users service
|
||||||
*
|
*
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
|
|
||||||
class UserServicesController extends Controller
|
|
||||||
{
|
|
||||||
public function services(User $o)
|
|
||||||
{
|
|
||||||
return ['data'=>$o->services_active->values()];
|
|
||||||
}
|
|
||||||
}
|
|
20
app/Interfaces/IDs.php
Normal file
20
app/Interfaces/IDs.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Interfaces;
|
||||||
|
|
||||||
|
interface IDs
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Return the local ID of the item
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getLIDattribute(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the system ID of the item
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getSIDattribute(): string;
|
||||||
|
}
|
@ -4,7 +4,8 @@ namespace App\Interfaces;
|
|||||||
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
interface ProductSupplier {
|
interface ProductSupplier
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Return the traffic inclusion with the service
|
* Return the traffic inclusion with the service
|
||||||
*
|
*
|
||||||
|
@ -3,12 +3,25 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Leenooks\Traits\ScopeActive;
|
||||||
|
|
||||||
|
use App\Interfaces\IDs;
|
||||||
use App\Traits\NextKey;
|
use App\Traits\NextKey;
|
||||||
|
|
||||||
class Account extends Model
|
/**
|
||||||
|
* Class Account
|
||||||
|
* Service Accounts
|
||||||
|
*
|
||||||
|
* Attributes for accounts:
|
||||||
|
* + lid: : Local ID for account
|
||||||
|
* + sid: : System ID for account
|
||||||
|
*
|
||||||
|
* @package App\Models
|
||||||
|
*/
|
||||||
|
class Account extends Model implements IDs
|
||||||
{
|
{
|
||||||
use NextKey;
|
use NextKey,ScopeActive;
|
||||||
|
|
||||||
const RECORD_ID = 'account';
|
const RECORD_ID = 'account';
|
||||||
public $incrementing = FALSE;
|
public $incrementing = FALSE;
|
||||||
|
|
||||||
@ -29,6 +42,8 @@ class Account extends Model
|
|||||||
'switch_url',
|
'switch_url',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/* RELATIONS */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the country the user belongs to
|
* Return the country the user belongs to
|
||||||
*/
|
*/
|
||||||
@ -69,15 +84,7 @@ class Account extends Model
|
|||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** SCOPES */
|
/* SCOPES */
|
||||||
|
|
||||||
/**
|
|
||||||
* Only query active categories
|
|
||||||
*/
|
|
||||||
public function scopeActive($query)
|
|
||||||
{
|
|
||||||
return $query->where('active',TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for a record
|
* Search for a record
|
||||||
@ -118,7 +125,7 @@ class Account extends Model
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ATTRIBUTES **/
|
/* ATTRIBUTES */
|
||||||
|
|
||||||
public function getActiveDisplayAttribute($value)
|
public function getActiveDisplayAttribute($value)
|
||||||
{
|
{
|
||||||
@ -144,10 +151,21 @@ class Account extends Model
|
|||||||
/**
|
/**
|
||||||
* Return the Account Unique Identifier
|
* Return the Account Unique Identifier
|
||||||
* @return string
|
* @return string
|
||||||
|
* @deprecated use getSIDAttribute()
|
||||||
*/
|
*/
|
||||||
public function getAIDAttribute()
|
public function getAIDAttribute()
|
||||||
{
|
{
|
||||||
return sprintf('%02s-%04s',$this->site_id,$this->id);
|
return $this->getSIDAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Account Local ID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLIDAttribute(): string
|
||||||
|
{
|
||||||
|
return sprintf('%04s',$this->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNameAttribute()
|
public function getNameAttribute()
|
||||||
@ -160,9 +178,19 @@ class Account extends Model
|
|||||||
return sprintf('%s <small>/%s</small>',$this->services()->noEagerLoads()->where('active',TRUE)->count(),$this->services()->noEagerLoads()->count());
|
return sprintf('%s <small>/%s</small>',$this->services()->noEagerLoads()->where('active',TRUE)->count(),$this->services()->noEagerLoads()->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Account System ID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSIDAttribute(): string
|
||||||
|
{
|
||||||
|
return sprintf('%02s-%s',$this->site_id,$this->getLIDAttribute());
|
||||||
|
}
|
||||||
|
|
||||||
public function getSwitchUrlAttribute()
|
public function getSwitchUrlAttribute()
|
||||||
{
|
{
|
||||||
return sprintf('<a href="/r/switch/start/%s"><i class="fa fa-external-link"></i></a>',$this->user_id);
|
return sprintf('<a href="/r/switch/start/%s"><i class="fas fa-external-link-alt"></i></a>',$this->user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTypeAttribute()
|
public function getTypeAttribute()
|
||||||
|
@ -6,14 +6,35 @@ use Carbon\Carbon;
|
|||||||
use Clarkeash\Doorman\Facades\Doorman;
|
use Clarkeash\Doorman\Facades\Doorman;
|
||||||
use Clarkeash\Doorman\Models\Invite;
|
use Clarkeash\Doorman\Models\Invite;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
use App\Traits\NextKey;
|
|
||||||
use App\Traits\PushNew;
|
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
|
use Leenooks\Traits\ScopeActive;
|
||||||
|
|
||||||
class Invoice extends Model
|
use App\Interfaces\IDs;
|
||||||
|
use App\Traits\{NextKey,PushNew};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Invoice
|
||||||
|
* Invoices that belong to an Account
|
||||||
|
*
|
||||||
|
* Attributes for services:
|
||||||
|
* + due : Balance due on an invoice
|
||||||
|
* + due_date : Date the invoice is due
|
||||||
|
* + invoice_date : Date the invoice was created
|
||||||
|
* + lid : Local ID for invoice
|
||||||
|
* + paid : Total of payments received (excluding pending)
|
||||||
|
* + paid_date : Date the invoice was paid in full
|
||||||
|
* + paid_pending : Total of pending payments received
|
||||||
|
* + sid : System ID for invoice
|
||||||
|
* + total_sub : Invoice sub-total before taxes
|
||||||
|
* + total_tax : Invoices total of taxes
|
||||||
|
* + total : Invoice total
|
||||||
|
*
|
||||||
|
* @package App\Models
|
||||||
|
*/
|
||||||
|
class Invoice extends Model implements IDs
|
||||||
{
|
{
|
||||||
use NextKey,PushNew;
|
use NextKey,PushNew,ScopeActive;
|
||||||
|
|
||||||
const RECORD_ID = 'invoice';
|
const RECORD_ID = 'invoice';
|
||||||
public $incrementing = FALSE;
|
public $incrementing = FALSE;
|
||||||
|
|
||||||
@ -33,8 +54,12 @@ class Invoice extends Model
|
|||||||
'paymentitems'
|
'paymentitems'
|
||||||
];
|
];
|
||||||
|
|
||||||
private $_total = 0;
|
// Caching variables
|
||||||
private $_total_tax = 0;
|
private int $_paid = 0;
|
||||||
|
private int $_total = 0;
|
||||||
|
private int $_total_tax = 0;
|
||||||
|
|
||||||
|
/* RELATIONS */
|
||||||
|
|
||||||
public function account()
|
public function account()
|
||||||
{
|
{
|
||||||
@ -43,7 +68,13 @@ class Invoice extends Model
|
|||||||
|
|
||||||
public function items()
|
public function items()
|
||||||
{
|
{
|
||||||
return $this->hasMany(InvoiceItem::class)->where('active',1);
|
return $this->hasMany(InvoiceItem::class)
|
||||||
|
->where('active',TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function payments()
|
||||||
|
{
|
||||||
|
return $this->hasManyThrough(Payment::class,PaymentItem::class,NULL,'id',NULL,'payment_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function paymentitems()
|
public function paymentitems()
|
||||||
@ -51,56 +82,114 @@ class Invoice extends Model
|
|||||||
return $this->hasMany(PaymentItem::class);
|
return $this->hasMany(PaymentItem::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** SCOPES **/
|
/* SCOPES */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for a record
|
* Search for a record
|
||||||
*
|
*
|
||||||
* @param $query
|
* @param $query
|
||||||
* @param string $term
|
* @param string $term
|
||||||
* @return
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function scopeSearch($query,string $term)
|
public function scopeSearch($query,string $term)
|
||||||
{
|
{
|
||||||
return $query->where('id','like','%'.$term.'%');
|
return $query->where('id','like','%'.$term.'%');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ATTRIBUTES **/
|
/* ATTRIBUTES */
|
||||||
|
|
||||||
public function getDueAttribute()
|
/**
|
||||||
|
* Balance due on an invoice
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDueAttribute(): float
|
||||||
{
|
{
|
||||||
return sprintf('%3.'.$this->currency()->rounding.'f',$this->total - $this->paid);
|
return sprintf('%4.'.$this->currency()->rounding.'f',$this->total-$this->paid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
* @deprecated use self::due_date;
|
||||||
|
*/
|
||||||
public function getDateDueAttribute()
|
public function getDateDueAttribute()
|
||||||
{
|
{
|
||||||
return $this->due_date->format('Y-m-d');
|
return $this->due_date->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInvoiceDateAttribute()
|
/**
|
||||||
|
* Date the invoices was created
|
||||||
|
*
|
||||||
|
* @return Carbon
|
||||||
|
*/
|
||||||
|
public function getInvoiceDateAttribute(): Carbon
|
||||||
{
|
{
|
||||||
return $this->date_orig->format('Y-m-d');
|
return $this->date_orig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get account System ID
|
||||||
|
* @return string
|
||||||
|
* @deprecated use getSIDAttribute()
|
||||||
|
*/
|
||||||
public function getInvoiceAccountIdAttribute()
|
public function getInvoiceAccountIdAttribute()
|
||||||
{
|
{
|
||||||
return sprintf('%02s-%04s-%06s',$this->site_id,$this->account_id,$this->invoice_id);
|
return $this->getSIDAttribute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @todo Move this to a site configuration
|
||||||
public function getInvoiceTextAttribute()
|
public function getInvoiceTextAttribute()
|
||||||
{
|
{
|
||||||
return sprintf('Thank you for using %s for your Internet Services.',config('SITE_SETUP')->site_name);
|
return sprintf('Thank you for using %s for your Internet Services.',config('SITE_SETUP')->site_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPaidAttribute()
|
/**
|
||||||
|
* Invoice Local ID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLIDAttribute(): string
|
||||||
{
|
{
|
||||||
return $this->currency()->round(
|
return sprintf('%06s',$this->id);
|
||||||
$this->paymentitems
|
|
||||||
->filter(function($item) { return ! $item->payment->pending_status; })
|
|
||||||
->sum('alloc_amt'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPendingPaidAttribute()
|
/**
|
||||||
|
* Total of payments received for this invoice
|
||||||
|
* excluding pending payments
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getPaidAttribute(): float
|
||||||
|
{
|
||||||
|
if (! $this->_paid)
|
||||||
|
$this->_paid = $this->currency()->round(
|
||||||
|
$this->paymentitems
|
||||||
|
->filter(function($item) { return ! $item->payment->pending_status; })
|
||||||
|
->sum('alloc_amt'));
|
||||||
|
|
||||||
|
return $this->_paid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the date that the invoice was paid in full.
|
||||||
|
* We assume the last payment received pays it in full.
|
||||||
|
*
|
||||||
|
* @return Carbon|null
|
||||||
|
*/
|
||||||
|
public function getPaidDateAttribute(): ?Carbon
|
||||||
|
{
|
||||||
|
$o = $this->payments
|
||||||
|
->filter(function($item) { return ! $item->pending_status; })
|
||||||
|
->last();
|
||||||
|
|
||||||
|
return $o ? $o->date_payment : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total of pending payments received for this invoice
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getPaidPendingAttribute(): float
|
||||||
{
|
{
|
||||||
return $this->currency()->round(
|
return $this->currency()->round(
|
||||||
$this->paymentitems
|
$this->paymentitems
|
||||||
@ -108,35 +197,87 @@ class Invoice extends Model
|
|||||||
->sum('alloc_amt'));
|
->sum('alloc_amt'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSubTotalAttribute()
|
/**
|
||||||
|
* Total of pending payments received for this invoice
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @deprecated use getPaidPendingAttribute()
|
||||||
|
*/
|
||||||
|
public function getPendingPaidAttribute(): float
|
||||||
|
{
|
||||||
|
return $this->getPaidPendingAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoice System ID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSIDAttribute(): string
|
||||||
|
{
|
||||||
|
return sprintf('%02s-%04s-%s',$this->site_id,$this->account_id,$this->getLIDAttribute());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get invoice subtotal before taxes
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
* @deprecated use getTotalSubAttribute()
|
||||||
|
*/
|
||||||
|
public function getSubTotalAttribute(): float
|
||||||
|
{
|
||||||
|
return $this->getTotalSubAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get invoice subtotal before taxes
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getTotalSubAttribute(): float
|
||||||
{
|
{
|
||||||
return sprintf('%3.'.$this->currency()->rounding.'f',$this->total-$this->tax_total);
|
return sprintf('%3.'.$this->currency()->rounding.'f',$this->total-$this->tax_total);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTaxTotalAttribute()
|
/**
|
||||||
|
* Get the invoices taxes total
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
* @deprecated use getTotalTaxAttribute();
|
||||||
|
*/
|
||||||
|
public function getTaxTotalAttribute(): float
|
||||||
|
{
|
||||||
|
return $this->getTotalTaxAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the invoices taxes total
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getTotalTaxAttribute(): float
|
||||||
{
|
{
|
||||||
if (! $this->_total_tax)
|
if (! $this->_total_tax)
|
||||||
{
|
foreach ($this->items as $o) {
|
||||||
foreach ($this->items as $o)
|
|
||||||
{
|
|
||||||
if ($o->active)
|
if ($o->active)
|
||||||
$this->_total_tax += $this->currency()->round($o->tax);
|
$this->_total_tax += $this->currency()->round($o->tax);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf('%3.'.$this->currency()->rounding.'f',$this->_total_tax);
|
return sprintf('%3.'.$this->currency()->rounding.'f',$this->_total_tax);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTotalAttribute()
|
/**
|
||||||
|
* Invoice total due
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTotalAttribute(): float
|
||||||
{
|
{
|
||||||
if (! $this->_total)
|
if (! $this->_total)
|
||||||
{
|
foreach ($this->items as $o) {
|
||||||
foreach ($this->items as $o)
|
|
||||||
{
|
|
||||||
if ($o->active)
|
if ($o->active)
|
||||||
$this->_total += $this->currency()->round($o->total);
|
$this->_total += $this->currency()->round($o->total);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf('%3.'.$this->currency()->rounding.'f',$this->_total);
|
return sprintf('%3.'.$this->currency()->rounding.'f',$this->_total);
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,25 @@ namespace App\Models;
|
|||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
use App\Traits\PushNew;
|
use App\Interfaces\IDs;
|
||||||
use App\Traits\NextKey;
|
use App\Traits\{NextKey,PushNew};
|
||||||
|
|
||||||
class Payment extends Model
|
/**
|
||||||
|
* Class Payment
|
||||||
|
* Payments that belong to an account
|
||||||
|
*
|
||||||
|
* Attributes for payments:
|
||||||
|
* + lid : Local ID for payment
|
||||||
|
* + payment_date : Date payment received
|
||||||
|
* + sid : System ID for payment
|
||||||
|
* + total : Payment total
|
||||||
|
*
|
||||||
|
* @package App\Models
|
||||||
|
*/
|
||||||
|
class Payment extends Model implements IDs
|
||||||
{
|
{
|
||||||
use NextKey,PushNew;
|
use NextKey,PushNew;
|
||||||
|
|
||||||
const RECORD_ID = 'payment';
|
const RECORD_ID = 'payment';
|
||||||
public $incrementing = FALSE;
|
public $incrementing = FALSE;
|
||||||
|
|
||||||
@ -24,6 +37,8 @@ class Payment extends Model
|
|||||||
// Array of items that can be updated with PushNew
|
// Array of items that can be updated with PushNew
|
||||||
protected $pushable = ['items'];
|
protected $pushable = ['items'];
|
||||||
|
|
||||||
|
/* RELATIONS */
|
||||||
|
|
||||||
public function account()
|
public function account()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Account::class);
|
return $this->belongsTo(Account::class);
|
||||||
@ -34,11 +49,37 @@ class Payment extends Model
|
|||||||
return $this->hasMany(PaymentItem::class);
|
return $this->hasMany(PaymentItem::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ATTRIBUTES */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
* @deprecated use date_payment directly.
|
||||||
|
*/
|
||||||
public function getDatePaidAttribute()
|
public function getDatePaidAttribute()
|
||||||
{
|
{
|
||||||
return $this->date_payment->format('Y-m-d');
|
return $this->date_payment->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payment Local ID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLIDattribute(): string
|
||||||
|
{
|
||||||
|
return sprintf('%06s',$this->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payment System ID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSIDAttribute(): string
|
||||||
|
{
|
||||||
|
return sprintf('%02s-%04s#%s',$this->site_id,$this->account_id,$this->getLIDattribute());
|
||||||
|
}
|
||||||
|
|
||||||
public function getTotalAttribute()
|
public function getTotalAttribute()
|
||||||
{
|
{
|
||||||
return sprintf('%3.'.$this->currency()->rounding.'f',$this->total_amt);
|
return sprintf('%3.'.$this->currency()->rounding.'f',$this->total_amt);
|
||||||
|
@ -4,12 +4,22 @@ namespace App\Models;
|
|||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
use App\Interfaces\IDs;
|
||||||
use App\Traits\NextKey;
|
use App\Traits\NextKey;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
class Product extends Model
|
/**
|
||||||
|
* Class Product
|
||||||
|
* Products that are available to sale, and appear on invoices
|
||||||
|
*
|
||||||
|
* Attributes for products:
|
||||||
|
* + lid : Local ID for product (part number)
|
||||||
|
*
|
||||||
|
* @package App\Models
|
||||||
|
*/
|
||||||
|
class Product extends Model implements IDs
|
||||||
{
|
{
|
||||||
use NextKey;
|
use NextKey;
|
||||||
const RECORD_ID = 'product';
|
const RECORD_ID = 'product';
|
||||||
@ -97,6 +107,16 @@ class Product extends Model
|
|||||||
return $this->description($this->getDefaultLanguage());
|
return $this->description($this->getDefaultLanguage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Product Local ID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLIDattribute(): string
|
||||||
|
{
|
||||||
|
return sprintf('%04s',$this->id);
|
||||||
|
}
|
||||||
|
|
||||||
public function getMinimumCostAttribute()
|
public function getMinimumCostAttribute()
|
||||||
{
|
{
|
||||||
$table = [
|
$table = [
|
||||||
@ -165,6 +185,16 @@ class Product extends Model
|
|||||||
return Arr::get($this->price_array,sprintf('%s.1.price_setup',$this->price_recurr_default))*1.1;
|
return Arr::get($this->price_array,sprintf('%s.1.price_setup',$this->price_recurr_default))*1.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Product System ID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSIDattribute(): string
|
||||||
|
{
|
||||||
|
return sprintf('%02s-%s',$this->site_id,$this->getLIDattribute());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return if this product captures usage data
|
* Return if this product captures usage data
|
||||||
*
|
*
|
||||||
|
@ -12,17 +12,30 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
|
|||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Leenooks\Carbon;
|
||||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
use Leenooks\Carbon;
|
use App\Interfaces\IDs;
|
||||||
use App\Traits\NextKey;
|
use App\Traits\NextKey;
|
||||||
|
|
||||||
class Service extends Model
|
/**
|
||||||
|
* Class Service
|
||||||
|
* Services that belong to an account
|
||||||
|
*
|
||||||
|
* Attributes for services:
|
||||||
|
* + name_short : Service Product short name, eg: phone number, domain name, certificate CN
|
||||||
|
* + sid : System ID for service
|
||||||
|
*
|
||||||
|
* @package App\Models
|
||||||
|
*/
|
||||||
|
class Service extends Model implements IDs
|
||||||
{
|
{
|
||||||
use NextKey;
|
use NextKey;
|
||||||
|
|
||||||
const RECORD_ID = 'service';
|
const RECORD_ID = 'service';
|
||||||
public $incrementing = FALSE;
|
public $incrementing = FALSE;
|
||||||
|
|
||||||
|
protected $table = 'ab_service';
|
||||||
const CREATED_AT = 'date_orig';
|
const CREATED_AT = 'date_orig';
|
||||||
const UPDATED_AT = 'date_last';
|
const UPDATED_AT = 'date_last';
|
||||||
|
|
||||||
@ -51,8 +64,6 @@ class Service extends Model
|
|||||||
];
|
];
|
||||||
public $dateFormat = 'U';
|
public $dateFormat = 'U';
|
||||||
|
|
||||||
protected $table = 'ab_service';
|
|
||||||
|
|
||||||
protected $visible = [
|
protected $visible = [
|
||||||
'account_name',
|
'account_name',
|
||||||
'admin_service_id_url',
|
'admin_service_id_url',
|
||||||
@ -268,6 +279,7 @@ class Service extends Model
|
|||||||
->where('item_type','=',0)
|
->where('item_type','=',0)
|
||||||
->orderBy('date_start');
|
->orderBy('date_start');
|
||||||
|
|
||||||
|
// @todo Change to $query->active();
|
||||||
if ($active)
|
if ($active)
|
||||||
$query->where('active','=',TRUE);
|
$query->where('active','=',TRUE);
|
||||||
|
|
||||||
@ -344,7 +356,7 @@ class Service extends Model
|
|||||||
public function scopeActive($query)
|
public function scopeActive($query)
|
||||||
{
|
{
|
||||||
return $query->where(function () use ($query) {
|
return $query->where(function () use ($query) {
|
||||||
$query->where('active',TRUE)
|
$query->where($this->getTable().'.active',TRUE)
|
||||||
->orWhereNotIn('order_status',$this->inactive_status);
|
->orWhereNotIn('order_status',$this->inactive_status);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -358,7 +370,7 @@ class Service extends Model
|
|||||||
public function scopeInActive($query)
|
public function scopeInActive($query)
|
||||||
{
|
{
|
||||||
return $query->where(function () use ($query) {
|
return $query->where(function () use ($query) {
|
||||||
$query->where('active',FALSE)
|
$query->where($this->getTable().'.active',FALSE)
|
||||||
->orWhereIn('order_status',$this->inactive_status);
|
->orWhereIn('order_status',$this->inactive_status);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -391,6 +403,7 @@ class Service extends Model
|
|||||||
* Name of the account for this service
|
* Name of the account for this service
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @deprecated use $this->>account->name directly
|
||||||
*/
|
*/
|
||||||
public function getAccountNameAttribute(): string
|
public function getAccountNameAttribute(): string
|
||||||
{
|
{
|
||||||
@ -409,6 +422,7 @@ class Service extends Model
|
|||||||
* Return the auto billing details
|
* Return the auto billing details
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @deprecated use billing directly?
|
||||||
*/
|
*/
|
||||||
public function getAutoPayAttribute()
|
public function getAutoPayAttribute()
|
||||||
{
|
{
|
||||||
@ -454,6 +468,7 @@ class Service extends Model
|
|||||||
* Date the service expires, also represents when it is paid up to
|
* Date the service expires, also represents when it is paid up to
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
* @todo
|
||||||
*/
|
*/
|
||||||
public function getExpiresAttribute(): string
|
public function getExpiresAttribute(): string
|
||||||
{
|
{
|
||||||
@ -613,6 +628,16 @@ class Service extends Model
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service Local ID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLIDattribute(): string
|
||||||
|
{
|
||||||
|
return sprintf('%05s',$this->id);
|
||||||
|
}
|
||||||
|
|
||||||
public function getNameAttribute(): string
|
public function getNameAttribute(): string
|
||||||
{
|
{
|
||||||
return $this->product->name_short.': '.$this->getNameShortAttribute();
|
return $this->product->name_short.': '.$this->getNameShortAttribute();
|
||||||
@ -670,6 +695,7 @@ class Service extends Model
|
|||||||
/**
|
/**
|
||||||
* Get the Product's Category for this service
|
* Get the Product's Category for this service
|
||||||
*
|
*
|
||||||
|
* @deprecated use product->category directly
|
||||||
*/
|
*/
|
||||||
public function getProductCategoryAttribute(): string
|
public function getProductCategoryAttribute(): string
|
||||||
{
|
{
|
||||||
@ -680,6 +706,7 @@ class Service extends Model
|
|||||||
* Get the Product's Short Name for the service
|
* Get the Product's Short Name for the service
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
* @deprecated use product->name directly
|
||||||
*/
|
*/
|
||||||
public function getProductNameAttribute(): string
|
public function getProductNameAttribute(): string
|
||||||
{
|
{
|
||||||
@ -717,13 +744,13 @@ class Service extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Services Unique Identifier
|
* Services System ID
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getSIDAttribute(): string
|
public function getSIDAttribute(): string
|
||||||
{
|
{
|
||||||
return sprintf('%02s-%04s.%05s',$this->site_id,$this->account_id,$this->id);
|
return sprintf('%02s-%04s.%s',$this->site_id,$this->account_id,$this->getLIDattribute());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -849,17 +876,19 @@ class Service extends Model
|
|||||||
|
|
||||||
/* SETTERS */
|
/* SETTERS */
|
||||||
|
|
||||||
|
// @todo is this required?
|
||||||
public function setDateOrigAttribute($value)
|
public function setDateOrigAttribute($value)
|
||||||
{
|
{
|
||||||
$this->attributes['date_orig'] = $value->timestamp;
|
$this->attributes['date_orig'] = $value->timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @todo is this required?
|
||||||
public function setDateLastAttribute($value)
|
public function setDateLastAttribute($value)
|
||||||
{
|
{
|
||||||
$this->attributes['date_last'] = $value->timestamp;
|
$this->attributes['date_last'] = $value->timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FUNCTIONS */
|
/* GENERAL METHODS */
|
||||||
|
|
||||||
// The action methods will return: NULL for no progress|FALSE for a failed status|next stage name.
|
// The action methods will return: NULL for no progress|FALSE for a failed status|next stage name.
|
||||||
|
|
||||||
|
@ -87,9 +87,11 @@ class Site extends Model
|
|||||||
|
|
||||||
public function getSiteLogoAttribute()
|
public function getSiteLogoAttribute()
|
||||||
{
|
{
|
||||||
$return = $this->getSiteDetailValue('site_logo')->value;
|
//$return = $this->getSiteDetailValue('site_logo')->value;
|
||||||
|
// @todo Get from DB.
|
||||||
|
$return = 'site/1/gth-horseradishfont-full.png';
|
||||||
|
|
||||||
return $return ? 'storage/'.$return : '/image/generic/150/20/fff';
|
return $return ? '/storage/'.$return : '/image/generic/150/20/fff';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getSiteDetailValue($key)
|
private function getSiteDetailValue($key)
|
||||||
|
@ -121,7 +121,8 @@ class User extends Authenticatable
|
|||||||
*/
|
*/
|
||||||
public function invoices()
|
public function invoices()
|
||||||
{
|
{
|
||||||
return $this->hasManyThrough(Invoice::class,Account::class);
|
return $this->hasManyThrough(Invoice::class,Account::class)
|
||||||
|
->active();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -141,7 +142,8 @@ class User extends Authenticatable
|
|||||||
*/
|
*/
|
||||||
public function services()
|
public function services()
|
||||||
{
|
{
|
||||||
return $this->hasManyThrough(Service::class,Account::class);
|
return $this->hasManyThrough(Service::class,Account::class)
|
||||||
|
->active();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -241,20 +243,6 @@ class User extends Authenticatable
|
|||||||
->reverse();
|
->reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The users active services
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getServicesActiveAttribute()
|
|
||||||
{
|
|
||||||
return $this->services
|
|
||||||
->filter(function($item)
|
|
||||||
{
|
|
||||||
return $item->isActive();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getServicesCountHtmlAttribute()
|
public function getServicesCountHtmlAttribute()
|
||||||
{
|
{
|
||||||
return sprintf('%s <small>/%s</small>',$this->services->where('active',TRUE)->count(),$this->services->count());
|
return sprintf('%s <small>/%s</small>',$this->services->where('active',TRUE)->count(),$this->services->count());
|
||||||
@ -523,7 +511,7 @@ class User extends Authenticatable
|
|||||||
DB::raw('ROUND(ab_invoice_item_tax.amount,2) AS tax'),
|
DB::raw('ROUND(ab_invoice_item_tax.amount,2) AS tax'),
|
||||||
|
|
||||||
])
|
])
|
||||||
->join('ab_invoice_item_tax',['ab_invoice_item_tax.invoice_item_id'=>'ab_invoice_item.id'])
|
->leftjoin('ab_invoice_item_tax',['ab_invoice_item_tax.invoice_item_id'=>'ab_invoice_item.id'])
|
||||||
->where('active',TRUE);
|
->where('active',TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,6 +536,7 @@ class User extends Authenticatable
|
|||||||
* Return an SQL query that will summarise invoices with payments
|
* Return an SQL query that will summarise invoices with payments
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Query\Builder
|
* @return \Illuminate\Database\Query\Builder
|
||||||
|
* @todo change this to just return outstanding invoices as a collection.
|
||||||
*/
|
*/
|
||||||
public function query_invoice_summary()
|
public function query_invoice_summary()
|
||||||
{
|
{
|
||||||
|
6
composer.lock
generated
6
composer.lock
generated
@ -2884,11 +2884,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "leenooks/laravel",
|
"name": "leenooks/laravel",
|
||||||
"version": "9.0.3",
|
"version": "9.0.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://dev.leenooks.net/leenooks/laravel",
|
"url": "https://dev.leenooks.net/leenooks/laravel",
|
||||||
"reference": "d4824ecda5187d8e9a81d5395f3f70145dff1b8d"
|
"reference": "9798f6aa7dcf507e7ac7179fc348320e36aa160b"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"creativeorange/gravatar": "^1.0",
|
"creativeorange/gravatar": "^1.0",
|
||||||
@ -2925,7 +2925,7 @@
|
|||||||
"laravel",
|
"laravel",
|
||||||
"leenooks"
|
"leenooks"
|
||||||
],
|
],
|
||||||
"time": "2021-06-28T02:50:28+00:00"
|
"time": "2021-06-29T06:38:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
|
8
public/css/custom.css
vendored
Normal file
8
public/css/custom.css
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
hr.d-print-block {
|
||||||
|
border-top: 2px solid #dee2e6;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table.table-striped tbody tr:last-child td {
|
||||||
|
border-bottom: 2px solid #dee2e6;
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
@if ($o->accounts->count() > 2)
|
@if ($o->accounts->count() > 1)
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<div class="info-box">
|
<div class="info-box">
|
||||||
<span class="info-box-icon bg-primary elevation-1"><i class="fa fa-user"></i></span>
|
<span class="info-box-icon bg-primary elevation-1"><i class="fas fa-user"></i></span>
|
||||||
|
|
||||||
<div class="info-box-content">
|
<div class="info-box-content">
|
||||||
<span class="info-box-text">Linked Accounts</span>
|
<span class="info-box-text">Linked Accounts</span>
|
||||||
@ -11,20 +11,20 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-2">
|
||||||
<div class="info-box">
|
<div class="info-box">
|
||||||
<span class="info-box-icon bg-info"><i class="fa fa-clone"></i></span>
|
<span class="info-box-icon bg-info"><i class="fas fa-clone"></i></span>
|
||||||
|
|
||||||
<div class="info-box-content">
|
<div class="info-box-content">
|
||||||
<span class="info-box-text">Active Services</span>
|
<span class="info-box-text">Active Services</span>
|
||||||
<span class="info-box-number">{{ $o->services_active->count() }} <small>/{{ $o->services->count() }}</small></span>
|
<span class="info-box-number">{{ $o->services->count() }} <small>/{{ $o->services->count() }}</small></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<div class="info-box">
|
<div class="info-box">
|
||||||
<span class="info-box-icon bg-danger"><i class="fa fa-dollar"></i></span>
|
<span class="info-box-icon bg-danger"><i class="fas fa-dollar-sign"></i></span>
|
||||||
|
|
||||||
<div class="info-box-content">
|
<div class="info-box-content">
|
||||||
<span class="info-box-text">Account Balance</span>
|
<span class="info-box-text">Account Balance</span>
|
||||||
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<div class="info-box">
|
<div class="info-box">
|
||||||
<span class="info-box-icon bg-dark"><i class="fa fa-hashtag"></i></span>
|
<span class="info-box-icon bg-dark"><i class="fas fa-hashtag"></i></span>
|
||||||
|
|
||||||
<div class="info-box-content">
|
<div class="info-box-content">
|
||||||
<span class="info-box-text">Invoices Due</span>
|
<span class="info-box-text">Invoices Due</span>
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
<div class="card card-info card-outline">
|
|
||||||
<div class="card-header">
|
|
||||||
<h4 class="card-title">Services</h4>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
@if ($o->services_active->count())
|
|
||||||
<table class="table table-striped table-hover" id="services" style="width: 100%;">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Category</th>
|
|
||||||
<th>Service</th>
|
|
||||||
<th>Product</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th>Next Invoice</th>
|
|
||||||
{{-- <th>Amount</th> --}}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th>Count {{ $o->services_active->count() }}</th>
|
|
||||||
<th colspan="5"> </th>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
@else
|
|
||||||
<p>No services active</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section('page-scripts')
|
|
||||||
@css('//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css','jq-dt-css','jquery')
|
|
||||||
@js('//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js','jq-dt-js','jquery')
|
|
||||||
@css('//cdn.datatables.net/responsive/2.2.1/css/responsive.dataTables.min.css','dt-responsive-css','jq-dt-css')
|
|
||||||
@js('//cdn.datatables.net/responsive/2.2.1/js/dataTables.responsive.min.js','dt-responsive-js','jq-dt-js')
|
|
||||||
@css('//cdn.datatables.net/rowgroup/1.0.2/css/rowGroup.dataTables.min.css','dt-rowgroup-css','jq-dt-css')
|
|
||||||
@js('//cdn.datatables.net/rowgroup/1.0.2/js/dataTables.rowGroup.min.js','dt-rowgroup-js','jq-dt-js')
|
|
||||||
@css('/plugin/dataTables/dataTables.bootstrap4.css','dt-bootstrap4-css','jq-dt-css')
|
|
||||||
@js('/plugin/dataTables/dataTables.bootstrap4.js','dt-bootstrap4-js','jq-dt-js')
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#services').DataTable( {
|
|
||||||
responsive: true,
|
|
||||||
ajax: {
|
|
||||||
url: "/api/u/services/{{ $o->id }}"
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{ data: "service_id_url" },
|
|
||||||
{ data: "product_category" },
|
|
||||||
{ data: "name_short" },
|
|
||||||
{ data: "product_name" },
|
|
||||||
{ data: "status" },
|
|
||||||
{ data: "next_invoice" },
|
|
||||||
{{-- { data: "billing_price", render: $.fn.dataTable.render.number(',','.',2,'$') } --}}
|
|
||||||
],
|
|
||||||
language: {
|
|
||||||
emptyTable: "No Active Services"
|
|
||||||
},
|
|
||||||
order: [5, 'asc'],
|
|
||||||
rowGroup: {
|
|
||||||
dataSrc: 'product_name',
|
|
||||||
startRender: null,
|
|
||||||
endRender: function ( rows, group ) {
|
|
||||||
return rows.count()+' x ' + group;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderFixed: [3, 'asc']
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#services tbody').on('click','tr', function () {
|
|
||||||
$(this).toggleClass('selected');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@append
|
|
@ -1,11 +1,6 @@
|
|||||||
<div class="card card-success card-outline">
|
<div class="card card-primary">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h4 class="card-title">Accounts</h4>
|
<h4 class="card-title">Accounts</h4>
|
||||||
|
|
||||||
<div class="card-tools">
|
|
||||||
<button type="button" class="btn btn-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
|
|
||||||
<button type="button" class="btn btn-tool" data-widget="remove"><i class="fa fa-remove"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -19,6 +14,7 @@
|
|||||||
<th>Services</th>
|
<th>Services</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Count {{ $user->all_accounts()->count() }}</th>
|
<th>Count {{ $user->all_accounts()->count() }}</th>
|
||||||
@ -26,6 +22,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@else
|
@else
|
||||||
<p>No Accounts Active</p>
|
<p>No Accounts Active</p>
|
||||||
@endif
|
@endif
|
@ -21,122 +21,56 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="card">
|
<div class="card-header bg-white">
|
||||||
<div class="card-header p-2">
|
<div class="card-header p-2">
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
<li class="nav-item"><a class="nav-link active" href="#tab-services" data-toggle="tab">Services</a></li>
|
<li class="nav-item"><a class="nav-link active" href="#tab-services" data-toggle="tab">Services</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#tab-clients" data-toggle="tab">Clients</a></li>
|
<li class="nav-item"><a class="nav-link" href="#tab-clients" data-toggle="tab">Clients</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body pl-0 pr-0">
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="active tab-pane" id="tab-services">
|
<div class="active tab-pane" id="tab-services">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-7">
|
<div class="col-7">
|
||||||
@include('common.service.widget.active')
|
@include('u.service.widgets.active')
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-5">
|
|
||||||
<!-- Show outstanding invoices -->
|
|
||||||
<div class="card card-warning card-outline">
|
|
||||||
<div class="card-header">
|
|
||||||
<h4 class="card-title">Outstanding Invoices</h4>
|
|
||||||
|
|
||||||
<div class="card-tools">
|
|
||||||
<button type="button" class="btn btn-tool" data-widget="collapse"><i class="fas fa-minus"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
@include('widgets.invoice',[
|
|
||||||
'o'=>$o->query_invoice_summary()->whereIN('account_id',$o->accounts()->pluck('id')->toArray())->having('balance','>',0),
|
|
||||||
'widget_invoice_name'=>'widget-invoice-outstanding'
|
|
||||||
])
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Show last 10 invoices -->
|
|
||||||
<div class="card card-warning card-outline">
|
|
||||||
<div class="card-header">
|
|
||||||
<h4 class="card-title">Invoices - Last 12 Months</h4>
|
|
||||||
|
|
||||||
<div class="card-tools">
|
|
||||||
<button type="button" class="btn btn-tool" data-widget="collapse"><i class="fas fa-minus"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
@include('widgets.invoice',[
|
|
||||||
'o'=>$o->query_invoice_summary()->whereIN('account_id',$o->accounts()->pluck('id')->toArray())->where('due_date','>',now()->subYear()->timestamp)->having('balance','=',0),
|
|
||||||
'widget_invoice_name'=>'widget-invoice-last'
|
|
||||||
])
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Show last 10 invoices -->
|
|
||||||
<div class="card card-warning card-outline">
|
|
||||||
<div class="card-header">
|
|
||||||
<h4 class="card-title">Payments - Last 12 Months</h4>
|
|
||||||
|
|
||||||
<div class="card-tools">
|
|
||||||
<button type="button" class="btn btn-tool" data-widget="collapse"><i class="fas fa-minus"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
@include('widgets.payment',[
|
|
||||||
'o'=>$o->query_payment_summary()->whereIN('account_id',$o->accounts()->pluck('id')->toArray())->where('date_payment','>',now()->subYear()->timestamp)->with(['items']),
|
|
||||||
'widget_payment_name'=>'widget-payment-last'
|
|
||||||
])
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="tab-pane" id="tab-clients">
|
<div class="col-5">
|
||||||
<div class="row">
|
@include('u.invoice.widgets.due')
|
||||||
<div class="col-4">
|
|
||||||
@include('r.account.widget.list')
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-8">
|
@include('u.invoice.widgets.list')
|
||||||
@include('r.service.widget.movement')
|
|
||||||
|
|
||||||
<!-- Show outstanding invoices -->
|
|
||||||
<div class="card card-warning card-outline">
|
|
||||||
<div class="card-header">
|
|
||||||
<h4 class="card-title">Outstanding Invoices</h4>
|
|
||||||
|
|
||||||
<div class="card-tools">
|
|
||||||
<button type="button" class="btn btn-tool" data-widget="collapse"><i class="fas fa-minus"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
@include('widgets.invoice',[
|
|
||||||
'o'=>$o->query_invoice_summary()->having('balance','>',0),
|
|
||||||
'widget_invoice_name'=>'widget-invoice-outstanding-client'
|
|
||||||
])
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{--
|
|
||||||
|
|
||||||
<div class="col-xs-6">
|
|
||||||
@include('r.agents')
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-6">
|
|
||||||
@include('r.clients')
|
|
||||||
</div>
|
|
||||||
--}}
|
|
||||||
|
|
||||||
|
@include('u.payment.widgets.list')
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div class="tab-pane" id="tab-clients">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">
|
||||||
|
@include('r.account.widgets.list')
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-8">
|
||||||
|
@include('r.service.widgets.movement')
|
||||||
|
|
||||||
|
@include('r.invoice.widgets.due')
|
||||||
|
</div>
|
||||||
|
{{--
|
||||||
|
|
||||||
|
<div class="col-xs-6">
|
||||||
|
@include('r.agents')
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
@include('r.clients')
|
||||||
|
</div>
|
||||||
|
--}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
<table class="table table-bordered">
|
|
||||||
<!-- Group by Account -->
|
|
||||||
@foreach (($x=$o->next_invoice_items($future))->groupBy('product_id') as $id => $oo)
|
|
||||||
<tr>
|
|
||||||
<th colspan="4">{{ $oo->first()->product->name }}</th>
|
|
||||||
<th class="text-right">${{ number_format($oo->sum('total'),2) }}</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
@foreach ($oo->groupBy('service_id') as $ooo)
|
|
||||||
<tr>
|
|
||||||
<td class="pt-0 pb-1" style="width: 8em;"><a href="{{ url('u/service',$ooo->first()->service_id) }}">{{ $ooo->first()->service->sid }}</a></td>
|
|
||||||
<td class="pt-0 pb-1" colspan="3">{{ $ooo->first()->service->sname }}: {{ $ooo->first()->service->sdesc }}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
@foreach ($ooo as $io)
|
|
||||||
<tr>
|
|
||||||
<td class="pt-0 pb-1"> </td>
|
|
||||||
<td class="pt-0 pb-1"> </td>
|
|
||||||
<td class="pt-0 pb-1">{{ $io->item_type_name }}</td>
|
|
||||||
<td class="text-right pt-0 pb-1">${{ number_format($io->total,2) }}</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
@endforeach
|
|
||||||
@endforeach
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<th colspan="4">TOTAL</th>
|
|
||||||
<th class="text-right">${{ number_format($x->sum('total'),2) }}</th>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
@ -0,0 +1,70 @@
|
|||||||
|
<!-- Show outstanding invoices for all clients -->
|
||||||
|
<div class="card card-warning">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Invoices Due</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
@if($o->query_invoice_summary()->having('balance','>',0)->count())
|
||||||
|
<table class="table table-bordered w-100" id="reseller_invoices_due">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Account</th>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Issued</th>
|
||||||
|
<th>Due</th>
|
||||||
|
<th class="text-right">Total</th>
|
||||||
|
<th class="text-right">Payments</th>
|
||||||
|
<th class="text-right">Outstanding</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach ($o->query_invoice_summary()->having('balance','>',0)->get() as $oo)
|
||||||
|
<tr @if ($oo->due_date->isPast()) class="table-danger" @endif>
|
||||||
|
<td>{{ $oo->account->name }}</td>
|
||||||
|
<td><a href="{{ url('u/invoice',$oo->id) }}">{{ $oo->sid }}</a></td>
|
||||||
|
<td>{{ $oo->date_orig->format('Y-m-d') }}</td>
|
||||||
|
<td>{{ $oo->due_date->format('Y-m-d') }}</td>
|
||||||
|
<td class="text-right">${{ number_format($oo->total,2) }}</td>
|
||||||
|
<td class="text-right">${{ number_format($oo->paid,2) }}</td>
|
||||||
|
<td class="text-right">${{ number_format($oo->due,2) }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@else
|
||||||
|
<p>No invoice due</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@section('page-scripts')
|
||||||
|
@css('//cdn.datatables.net/1.10.25/css/dataTables.bootstrap5.min.css','jq-dt-css','jquery')
|
||||||
|
@js('//cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js','jq-dt-js','jquery')
|
||||||
|
@js('//cdn.datatables.net/1.10.25/js/dataTables.bootstrap5.min.js','jq-dt-bs5-js','jq-dt-js')
|
||||||
|
@js('//cdn.datatables.net/rowgroup/1.1.3/js/dataTables.rowGroup.min.js','jq-dt-rowgroup-js','jq-dt-js')
|
||||||
|
@css('//cdn.datatables.net/rowgroup/1.1.3/css/rowGroup.bootstrap5.min.css','jq-dt-rowgroup-css','jq-dt-jss')
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#reseller_invoices_due').DataTable({
|
||||||
|
order: [[0,'asc'],[3,'desc']],
|
||||||
|
rowGroup: {
|
||||||
|
dataSrc: 0,
|
||||||
|
},
|
||||||
|
columnDefs: [
|
||||||
|
{
|
||||||
|
targets: [0],
|
||||||
|
visible: false,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#invoices_due tbody').on('click','tr', function () {
|
||||||
|
$(this).toggleClass('selected');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@append
|
@ -1,17 +1,12 @@
|
|||||||
<!-- Show client movements -->
|
<!-- Show client movements -->
|
||||||
<div class="card card-warning card-outline">
|
<div class="card card-danger">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h4 class="card-title">Service Movements</h4>
|
<h3 class="card-title">Service Movements</h3>
|
||||||
|
|
||||||
<div class="card-tools">
|
|
||||||
<button type="button" class="btn btn-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
|
|
||||||
<button type="button" class="btn btn-tool" data-widget="remove"><i class="fa fa-remove"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@if (($x=$user->client_service_movements())->count())
|
@if (($x=$user->client_service_movements())->count())
|
||||||
<table class="table table-striped table-hover" id="service_movements" style="width: 100%;">
|
<table class="table table-striped table-hover" id="service_movements">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
@ -21,10 +16,11 @@
|
|||||||
<th>Product</th>
|
<th>Product</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach ($x as $o)
|
@foreach ($x as $o)
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{{ url('u/service',$o->id) }}">{{ $o->id }}</a></td>
|
<td><a href="{{ url('u/service',$o->id) }}">{{ $o->sid }}</a></td>
|
||||||
<td>{{ $o->account->name }}</td>
|
<td>{{ $o->account->name }}</td>
|
||||||
<td>{{ $o->name_short }}</td>
|
<td>{{ $o->name_short }}</td>
|
||||||
<td>
|
<td>
|
||||||
@ -45,6 +41,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Count {{ $x->count() }}</th>
|
<th>Count {{ $x->count() }}</th>
|
||||||
@ -59,19 +56,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
@css('//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css','jq-dt-css','jquery')
|
@css('//cdn.datatables.net/1.10.25/css/dataTables.bootstrap5.min.css','jq-dt-css','jquery')
|
||||||
@js('//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js','jq-dt-js','jquery')
|
@js('//cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js','jq-dt-js','jquery')
|
||||||
@css('//cdn.datatables.net/responsive/2.2.1/css/responsive.dataTables.min.css','dt-responsive-css','jq-dt-css')
|
@js('//cdn.datatables.net/1.10.25/js/dataTables.bootstrap5.min.js','jq-dt-bs5-js','jq-dt-js')
|
||||||
@js('//cdn.datatables.net/responsive/2.2.1/js/dataTables.responsive.min.js','dt-responsive-js','jq-dt-js')
|
@js('//cdn.datatables.net/rowgroup/1.1.3/js/dataTables.rowGroup.min.js','jq-dt-rowgroup-js','jq-dt-js')
|
||||||
@css('//cdn.datatables.net/rowgroup/1.0.2/css/rowGroup.dataTables.min.css','dt-rowgroup-css','jq-dt-css')
|
@css('//cdn.datatables.net/rowgroup/1.1.3/css/rowGroup.bootstrap5.min.css','jq-dt-rowgroup-css','jq-dt-jss')
|
||||||
@js('//cdn.datatables.net/rowgroup/1.0.2/js/dataTables.rowGroup.min.js','dt-rowgroup-js','jq-dt-js')
|
|
||||||
@css('/plugin/dataTables/dataTables.bootstrap4.css','dt-bootstrap4-css','jq-dt-css')
|
|
||||||
@js('/plugin/dataTables/dataTables.bootstrap4.js','dt-bootstrap4-js','jq-dt-js')
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('#service_movements').DataTable( {
|
$('#service_movements').DataTable( {
|
||||||
responsive: true,
|
|
||||||
order: [3, 'asc'],
|
order: [3, 'asc'],
|
||||||
rowGroup: {
|
rowGroup: {
|
||||||
dataSrc: 1,
|
dataSrc: 1,
|
@ -20,95 +20,45 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card-header bg-white">
|
||||||
<div class="card-header p-2">
|
<ul class="nav nav-pills">
|
||||||
<ul class="nav nav-pills">
|
<li class="nav-item"><a class="nav-link active" href="#tab-services" data-toggle="tab">Services</a></li>
|
||||||
<li class="nav-item"><a class="nav-link active" href="#tab-services" data-toggle="tab">Services</a></li>
|
<li class="nav-item"><a class="nav-link" href="#tab-nextinvoice" data-toggle="tab">Next Invoice</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#tab-nextinvoice" data-toggle="tab">Next Invoice</a></li>
|
<li class="nav-item"><a class="nav-link" href="#tab-futureinvoice" data-toggle="tab">Future Invoice</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#tab-futureinvoice" data-toggle="tab">Future Invoice</a></li>
|
</ul>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body pl-0 pr-0">
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="active tab-pane" id="tab-services">
|
<div class="active tab-pane" id="tab-services">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-7">
|
<div class="col-7">
|
||||||
@include('common.service.widget.active')
|
@include('u.service.widgets.active')
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-5">
|
<div class="col-5">
|
||||||
<!-- Show outstanding invoices -->
|
@include('u.invoice.widgets.due')
|
||||||
<div class="card card-warning card-outline">
|
|
||||||
<div class="card-header">
|
|
||||||
<h4 class="card-title">Outstanding Invoices</h4>
|
|
||||||
|
|
||||||
<div class="card-tools">
|
@include('u.invoice.widgets.list')
|
||||||
<button type="button" class="btn btn-tool" data-widget="collapse"><i class="fas fa-minus"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body">
|
@include('u.payment.widgets.list')
|
||||||
@include('widgets.invoice',[
|
|
||||||
'o'=>$o->query_invoice_summary()->whereIN('account_id',$o->accounts()->pluck('id')->toArray())->having('balance','>',0),
|
|
||||||
'widget_invoice_name'=>'widget-invoice'
|
|
||||||
])
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Show last 10 invoices -->
|
|
||||||
<div class="card card-warning card-outline">
|
|
||||||
<div class="card-header">
|
|
||||||
<h4 class="card-title">Invoices - Last 12 Months</h4>
|
|
||||||
|
|
||||||
<div class="card-tools">
|
|
||||||
<button type="button" class="btn btn-tool" data-widget="collapse"><i class="fas fa-minus"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
@include('widgets.invoice',[
|
|
||||||
'o'=>$o->query_invoice_summary()->whereIN('account_id',$o->accounts()->pluck('id')->toArray())->where('due_date','>',now()->subYear()->timestamp)->having('balance','=',0),
|
|
||||||
'widget_invoice_name'=>'widget-invoice-last'
|
|
||||||
])
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Show last 10 invoices -->
|
|
||||||
<div class="card card-warning card-outline">
|
|
||||||
<div class="card-header">
|
|
||||||
<h4 class="card-title">Payments - Last 12 Months</h4>
|
|
||||||
|
|
||||||
<div class="card-tools">
|
|
||||||
<button type="button" class="btn btn-tool" data-widget="collapse"><i class="fas fa-minus"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
@include('widgets.payment',[
|
|
||||||
'o'=>$o->query_payment_summary()->where('date_payment','>',now()->subYear()->timestamp)->with(['items']),
|
|
||||||
'widget_payment_name'=>'widget-payment-last'
|
|
||||||
])
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane" id="tab-nextinvoice">
|
<div class="tab-pane" id="tab-nextinvoice">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
@include('r.invoice.widget.next',['future'=>FALSE])
|
@include('u.invoice.widgets.next',['future'=>FALSE])
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane" id="tab-futureinvoice">
|
<div class="tab-pane" id="tab-futureinvoice">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
@include('r.invoice.widget.next',['future'=>TRUE])
|
@include('u.invoice.widgets.next',['future'=>TRUE])
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
@section('htmlheader_title')
|
@section('htmlheader_title')
|
||||||
Payment Cart
|
Payment Cart
|
||||||
@endsection
|
@endsection
|
||||||
|
@section('page_title')
|
||||||
|
Payments
|
||||||
|
@endsection
|
||||||
|
|
||||||
@section('contentheader_title')
|
@section('contentheader_title')
|
||||||
Payment Cart
|
Payment Cart
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
@extends('adminlte::layouts.app')
|
@extends('adminlte::layouts.app')
|
||||||
|
|
||||||
@section('htmlheader_title')
|
@section('htmlheader_title')
|
||||||
Invoice #{{ $o->id }}
|
Invoice #{{ $o->lid }}
|
||||||
|
@endsection
|
||||||
|
@section('page_title')
|
||||||
|
{{ $o->sid }}
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('contentheader_title')
|
@section('contentheader_title')
|
||||||
Invoice #{{ $o->id }}
|
Tax Invoice <strong>#{{ $o->lid }}</strong>
|
||||||
@endsection
|
@endsection
|
||||||
@section('contentheader_description')
|
@section('contentheader_description')
|
||||||
{{ $o->invoice_account_id }}
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('main-content')
|
@section('main-content')
|
||||||
@ -16,11 +18,14 @@
|
|||||||
<div class="invoice p-3 mb-3">
|
<div class="invoice p-3 mb-3">
|
||||||
<!-- title row -->
|
<!-- title row -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-8">
|
||||||
<h4>
|
<h2>
|
||||||
<i class="fa fa-globe"></i> {{ $so->site_name }}
|
<img src="{{ $so->site_logo }}">
|
||||||
<small class="float-right">Date: {{ $o->invoice_date}}</small>
|
</h2>
|
||||||
</h4>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-4 text-right">
|
||||||
|
<h1 class="text-uppercase">Tax Invoice</h1>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.col -->
|
<!-- /.col -->
|
||||||
</div>
|
</div>
|
||||||
@ -54,17 +59,26 @@
|
|||||||
<div class="ml-auto col-3">
|
<div class="ml-auto col-3">
|
||||||
<table class="table table-borderless text-right" style="font-size: 1.1rem;">
|
<table class="table table-borderless text-right" style="font-size: 1.1rem;">
|
||||||
<tr >
|
<tr >
|
||||||
<td class="p-0">Account:</td><td class="p-0"><strong>{{ $o->account->account_id }}</strong></td>
|
<td class="p-0">Issue Date:</td><td class="p-0"><strong>{{ $o->invoice_date->format('Y-m-d') }}</strong></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr >
|
<tr >
|
||||||
<td class="p-0">Invoice:</td><td class="p-0"><strong>{{ $o->invoice_id }}</strong></td>
|
<td class="p-0">Account:</td><td class="p-0"><strong>{{ $o->account->sid }}</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr >
|
||||||
|
<td class="p-0">Invoice:</td><td class="p-0"><strong>{{ $o->lid }}</strong></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="p-0">Payment Due:</td><td class="p-0"><strong>{{ $o->due_date->format('Y-m-d') }}</strong></td>
|
<td class="p-0">Payment Due:</td><td class="p-0"><strong>{{ $o->due_date->format('Y-m-d') }}</strong></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="p-0">Total Due:</td><td class="p-0"><strong>${{ number_format($o->total,$o->currency()->rounding) }}</strong></td>
|
<td class="p-0">This Invoice Due:</td><td class="p-0"><strong>${{ number_format($o->total,$o->currency()->rounding) }}</strong></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{{--
|
||||||
|
<!-- @todo -->
|
||||||
|
<tr>
|
||||||
|
<td class="p-0">Total Account Due:</td><td class="p-0"><strong>${{ number_format($o->account->due,$o->currency()->rounding) }}</strong></td>
|
||||||
|
</tr>
|
||||||
|
--}}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -73,7 +87,7 @@
|
|||||||
<!-- Table row -->
|
<!-- Table row -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 table-responsive">
|
<div class="col-12 table-responsive">
|
||||||
<table id="restripe" class="table" width="100%">
|
<table class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Qty</th>
|
<th>Qty</th>
|
||||||
@ -87,20 +101,22 @@
|
|||||||
@foreach ($o->products() as $po)
|
@foreach ($o->products() as $po)
|
||||||
<tr id="invoice-services">
|
<tr id="invoice-services">
|
||||||
<td>{{ $po->count }}</td>
|
<td>{{ $po->count }}</td>
|
||||||
<td>{{ $po->product_id }}</td>
|
<td>#{{ $po->lid }}</td>
|
||||||
<td colspan="2">{{ $po->name($o->account->user->language) }}</td>
|
<td colspan="2">{{ $po->name($o->account->user->language) }}</td>
|
||||||
<td colspan="3" class="text-right">${{ number_format($o->items->filter(function($item) use ($po) {return $item->product_id == $po->id; })->sum('total'),$o->currency()->rounding) }}</td>
|
<td colspan="3" class="text-right">${{ number_format($o->items->filter(function($item) use ($po) {return $item->product_id == $po->id; })->sum('total'),$o->currency()->rounding) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@foreach ($o->product_services($po) as $so)
|
@foreach ($o->product_services($po) as $so)
|
||||||
<tr id="invoice-service-items" class="invoice-services d-none @if($o->products()->count() > 1) d-print-table-row @endif">
|
<tr id="invoice-service-items" class="invoice-services @if($o->products()->count() > 1) d-print-table-row @endif">
|
||||||
<td colspan="2"> </td>
|
<td colspan="2"> </td>
|
||||||
<td colspan="2">Service: <strong>{{ $so->service_id }}: {{ $so->name }}</strong></td>
|
<td colspan="2">Service: <strong>{{ $so->sid }}: {{ $so->name }}</strong></td>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
<td class="text-right">${{ number_format($o->product_service_items($po,$so)->sum('total'),$o->currency()->rounding) }}</td>
|
<td class="text-right">${{ number_format($o->product_service_items($po,$so)->sum('total'),$o->currency()->rounding) }}</td>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@foreach ($o->product_service_items($po,$so) as $io)
|
@foreach ($o->product_service_items($po,$so) as $io)
|
||||||
<tr class="invoice-service-items d-none d-print-table-row">
|
<tr class="invoice-service-items d-print-table-row">
|
||||||
<td colspan="2"> </td>
|
<td colspan="2"> </td>
|
||||||
<td width="5%"> </td>
|
<td width="5%"> </td>
|
||||||
<td>{{ $io->item_type_name }}</td>
|
<td>{{ $io->item_type_name }}</td>
|
||||||
@ -117,6 +133,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- /.row -->
|
<!-- /.row -->
|
||||||
|
|
||||||
|
<!-- padding -->
|
||||||
|
<div class="row pb-5"></div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- accepted payments column -->
|
<!-- accepted payments column -->
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
@ -138,16 +157,17 @@
|
|||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2" style="width:50%">Subtotal:</th>
|
<th colspan="2" style="width:50%">Subtotal:</th>
|
||||||
<td class="text-right">${{ number_format($o->sub_total,$o->currency()->rounding) }}</td>
|
<td class="text-right">${{ number_format($o->total_sub,$o->currency()->rounding) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
<th>Tax (GST 10%)</th>
|
<th>Tax (GST 10%)</th>
|
||||||
<td class="text-right">${{ number_format($o->tax_total,$o->currency()->rounding) }}</td>
|
<td class="text-right">${{ number_format($o->total_tax,$o->currency()->rounding) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
<th>Other Charges:</th>
|
<th>Other Charges:</th>
|
||||||
|
<!-- @todo -->
|
||||||
<td class="text-right">$0.00</td>
|
<td class="text-right">$0.00</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -158,23 +178,17 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
<th>Payments To Clear:</th>
|
<th>Payments To Clear:</th>
|
||||||
<td class="text-right">${{ number_format($o->pending_paid,$o->currency()->rounding) }}</td>
|
<td class="text-right">${{ number_format($o->paid_pending,$o->currency()->rounding) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
<th>Payments:</th>
|
<th>Payments:</th>
|
||||||
<td class="text-right">${{ number_format($o->paid,$o->currency()->rounding) }}</td>
|
<td class="text-right">${{ number_format($o->paid,$o->currency()->rounding) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr style="font-size: 145%">
|
||||||
<th colspan="2">Invoice Total Due:</th>
|
<th colspan="2">Invoice Due:</th>
|
||||||
<td class="text-right">${{ number_format($o->due,$o->currency()->rounding) }}</td>
|
<td class="text-right">${{ number_format($o->due,$o->currency()->rounding) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{--
|
|
||||||
<tr>
|
|
||||||
<th colspan="2">Account Due:</th>
|
|
||||||
<td class="text-right">${{ number_format($o->account->due,$o->currency()->rounding) }}</td>
|
|
||||||
</tr>
|
|
||||||
--}}
|
|
||||||
@endif
|
@endif
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -185,13 +199,13 @@
|
|||||||
<!-- this row will not appear when printing -->
|
<!-- this row will not appear when printing -->
|
||||||
<div class="row d-print-none">
|
<div class="row d-print-none">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<a href="javascript:window.print();" class="btn btn-default"><i class="fa fa-print"></i> Print</a>
|
<a href="javascript:window.print();" class="btn btn-default"><i class="fas fa-print"></i> Print</a>
|
||||||
@if($o->id)
|
@if($o->id)
|
||||||
<a href="{{ url('u/invoice/cart',$o->id) }}" class="btn btn-success float-right">
|
<a href="{{ url('u/invoice/cart',$o->id) }}" class="btn btn-success float-right">
|
||||||
<i class="fa fa-credit-card"></i> Pay
|
<i class="fas fa-credit-card"></i> Pay
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ url(sprintf('u/invoice/%s/pdf',$o->id)) }}" class="btn btn-primary float-right mr-2">
|
<a href="{{ url(sprintf('u/invoice/%s/pdf',$o->id)) }}" class="btn btn-primary float-right mr-2">
|
||||||
<i class="fa fa-download"></i> Download PDF
|
<i class="fas fa-download"></i> Download PDF
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@ -201,32 +215,3 @@
|
|||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('page-scripts')
|
|
||||||
<style>
|
|
||||||
.stripe-odd {
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
}
|
|
||||||
.stripe-even {
|
|
||||||
background-color: #e9e9e9;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function() {
|
|
||||||
$("table#restripe").removeClass("table-striped");
|
|
||||||
|
|
||||||
$("table#restripe tr:not(.d-print-table-row)").each(function (index) {
|
|
||||||
$(this).toggleClass("stripe-odd", (index & 1));
|
|
||||||
$(this).toggleClass("stripe-even", !!(index & 1));
|
|
||||||
});
|
|
||||||
|
|
||||||
$('tr[id="invoice-services"]').click(function() {
|
|
||||||
$(".invoice-services").toggleClass("d-none");
|
|
||||||
});
|
|
||||||
|
|
||||||
$('tr[id="invoice-service-items"]').click(function() {
|
|
||||||
$(".invoice-service-items").toggleClass("d-none");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
@append
|
|
@ -0,0 +1,70 @@
|
|||||||
|
<!-- Show outstanding invoices -->
|
||||||
|
<div class="card card-warning">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Invoices Due</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
@if($o->invoices->where('due','>',0)->count())
|
||||||
|
<table class="table table-bordered w-100" id="invoices_due">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Account</th>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Issued</th>
|
||||||
|
<th>Due</th>
|
||||||
|
<th class="text-right">Total</th>
|
||||||
|
<th class="text-right">Payments</th>
|
||||||
|
<th class="text-right">Outstanding</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach ($o->invoices->where('due','>',0) as $oo)
|
||||||
|
<tr @if ($oo->due_date->isPast()) class="table-danger" @endif>
|
||||||
|
<td>{{ $oo->account->name }}</td>
|
||||||
|
<td><a href="{{ url('u/invoice',$oo->id) }}">{{ $oo->sid }}</a></td>
|
||||||
|
<td>{{ $oo->date_orig->format('Y-m-d') }}</td>
|
||||||
|
<td>{{ $oo->due_date->format('Y-m-d') }}</td>
|
||||||
|
<td class="text-right">${{ number_format($oo->total,2) }}</td>
|
||||||
|
<td class="text-right">${{ number_format($oo->paid,2) }}</td>
|
||||||
|
<td class="text-right">${{ number_format($oo->due,2) }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@else
|
||||||
|
<p>No invoice due</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@section('page-scripts')
|
||||||
|
@css('//cdn.datatables.net/1.10.25/css/dataTables.bootstrap5.min.css','jq-dt-css','jquery')
|
||||||
|
@js('//cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js','jq-dt-js','jquery')
|
||||||
|
@js('//cdn.datatables.net/1.10.25/js/dataTables.bootstrap5.min.js','jq-dt-bs5-js','jq-dt-js')
|
||||||
|
@js('//cdn.datatables.net/rowgroup/1.1.3/js/dataTables.rowGroup.min.js','jq-dt-rowgroup-js','jq-dt-js')
|
||||||
|
@css('//cdn.datatables.net/rowgroup/1.1.3/css/rowGroup.bootstrap5.min.css','jq-dt-rowgroup-css','jq-dt-jss')
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#invoices_due').DataTable({
|
||||||
|
order: [[0,'asc'],[3,'desc']],
|
||||||
|
rowGroup: {
|
||||||
|
dataSrc: 0,
|
||||||
|
},
|
||||||
|
columnDefs: [
|
||||||
|
{
|
||||||
|
targets: [0],
|
||||||
|
visible: false,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#invoices_due tbody').on('click','tr', function () {
|
||||||
|
$(this).toggleClass('selected');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@append
|
@ -0,0 +1,68 @@
|
|||||||
|
<!-- Show past 12 months invoices -->
|
||||||
|
<div class="card card-success">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Past Invoices</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
@if($o->invoices->where('date_orig','>',($x=\Carbon\Carbon::now()->subMonths(12)))->where('due','=',0)->count())
|
||||||
|
<table class="table table-bordered w-100" id="invoices_past">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Account</th>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Issued</th>
|
||||||
|
<th>Due</th>
|
||||||
|
<th>Paid</th>
|
||||||
|
<th class="text-right">Total</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach ($o->invoices->where('date_orig','>',$x)->where('due','=',0) as $oo)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $oo->account->name }}</td>
|
||||||
|
<td><a href="{{ url('u/invoice',$oo->id) }}">{{ $oo->sid }}</a></td>
|
||||||
|
<td>{{ $oo->date_orig->format('Y-m-d') }}</td>
|
||||||
|
<td>{{ $oo->due_date->format('Y-m-d') }}</td>
|
||||||
|
<td>{{ $oo->paid_date ? $oo->paid_date->format('Y-m-d') : '' }}</td>
|
||||||
|
<td class="text-right">${{ number_format($oo->total,2) }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@else
|
||||||
|
<p>No invoices to list</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@section('page-scripts')
|
||||||
|
@css('//cdn.datatables.net/1.10.25/css/dataTables.bootstrap5.min.css','jq-dt-css','jquery')
|
||||||
|
@js('//cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js','jq-dt-js','jquery')
|
||||||
|
@js('//cdn.datatables.net/1.10.25/js/dataTables.bootstrap5.min.js','jq-dt-bs5-js','jq-dt-js')
|
||||||
|
@js('//cdn.datatables.net/rowgroup/1.1.3/js/dataTables.rowGroup.min.js','jq-dt-rowgroup-js','jq-dt-js')
|
||||||
|
@css('//cdn.datatables.net/rowgroup/1.1.3/css/rowGroup.bootstrap5.min.css','jq-dt-rowgroup-css','jq-dt-jss')
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#invoices_past').DataTable({
|
||||||
|
order: [[0,'asc'],[3,'desc']],
|
||||||
|
rowGroup: {
|
||||||
|
dataSrc: 0,
|
||||||
|
},
|
||||||
|
columnDefs: [
|
||||||
|
{
|
||||||
|
targets: [0],
|
||||||
|
visible: false,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#invoices_past tbody').on('click','tr', function () {
|
||||||
|
$(this).toggleClass('selected');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@append
|
@ -0,0 +1,40 @@
|
|||||||
|
<!-- Show next items for an invoice -->
|
||||||
|
@if ($o->next_invoice_items($future)->count())
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table">
|
||||||
|
<!-- Group by Account -->
|
||||||
|
@foreach (($x=$o->next_invoice_items($future))->groupBy('product_id') as $id => $oo)
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">{{ $oo->first()->product->name }}</th>
|
||||||
|
<th class="text-right">${{ number_format($oo->sum('total'),2) }}</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
@foreach ($oo->groupBy('service_id') as $ooo)
|
||||||
|
<tr>
|
||||||
|
<td class="pt-0 pb-1" style="width: 8em;"><a href="{{ url('u/service',$ooo->first()->service_id) }}">{{ $ooo->first()->service->sid }}</a></td>
|
||||||
|
<td class="pt-0 pb-1" colspan="3">{{ $ooo->first()->service->sname }}: {{ $ooo->first()->service->sdesc }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
@foreach ($ooo as $io)
|
||||||
|
<tr>
|
||||||
|
<td class="pt-0 pb-1"> </td>
|
||||||
|
<td class="pt-0 pb-1"> </td>
|
||||||
|
<td class="pt-0 pb-1">{{ $io->item_type_name }}</td>
|
||||||
|
<td class="text-right pt-0 pb-1">${{ number_format($io->total,2) }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
@endforeach
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th class="text-right" colspan="4">TOTAL</th>
|
||||||
|
<th class="text-right">${{ number_format($x->sum('total'),2) }}</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@else
|
||||||
|
<p>No items currently due to invoice.</p>
|
||||||
|
@endif
|
@ -0,0 +1,73 @@
|
|||||||
|
<!-- Show past 12 months payments -->
|
||||||
|
<div class="card card-success">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Past Payments</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
@if($o->payments->where('date_orig','>',($x=\Carbon\Carbon::now()->subMonths(12)))->count())
|
||||||
|
<table class="table table-bordered w-100" id="payments_past">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Account</th>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Received</th>
|
||||||
|
<th class="text-right">Total</th>
|
||||||
|
{{--<th class="text-right">Balance</th>--}}
|
||||||
|
<th>Invoice(s)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach ($o->payments->where('date_orig','>',($x=\Carbon\Carbon::now()->subMonths(12))) as $oo)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $oo->account->name }}</td>
|
||||||
|
<td>{{ $oo->sid }}</td>
|
||||||
|
<td>{{ $oo->date_payment->format('Y-m-d') }}</td>
|
||||||
|
<td class="text-right">${{ number_format($oo->total,2) }}</td>
|
||||||
|
{{--<td class="text-right">${{ number_format($oo->balance,2) }}</td>--}}
|
||||||
|
<td>
|
||||||
|
{!! join(', ',$oo->items
|
||||||
|
->filter(function($item) { return $item->invoice_id; })
|
||||||
|
->transform(function($item) { return sprintf('<a href="%s">%s</a>',url('u/invoice',$item->invoice_id),$item->invoice_id); })
|
||||||
|
->toArray()) !!}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@else
|
||||||
|
<p>No payments to list</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@section('page-scripts')
|
||||||
|
@css('//cdn.datatables.net/1.10.25/css/dataTables.bootstrap5.min.css','jq-dt-css','jquery')
|
||||||
|
@js('//cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js','jq-dt-js','jquery')
|
||||||
|
@js('//cdn.datatables.net/1.10.25/js/dataTables.bootstrap5.min.js','jq-dt-bs5-js','jq-dt-js')
|
||||||
|
@js('//cdn.datatables.net/rowgroup/1.1.3/js/dataTables.rowGroup.min.js','jq-dt-rowgroup-js','jq-dt-js')
|
||||||
|
@css('//cdn.datatables.net/rowgroup/1.1.3/css/rowGroup.bootstrap5.min.css','jq-dt-rowgroup-css','jq-dt-jss')
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#payments_past').DataTable({
|
||||||
|
order: [2,'desc'],
|
||||||
|
rowGroup: {
|
||||||
|
dataSrc: 0,
|
||||||
|
},
|
||||||
|
columnDefs: [
|
||||||
|
{
|
||||||
|
targets: [0],
|
||||||
|
visible: false,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#payments_past tbody').on('click','tr', function () {
|
||||||
|
$(this).toggleClass('selected');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@append
|
@ -88,7 +88,7 @@
|
|||||||
</div>
|
</div>
|
||||||
@can('wholesaler')
|
@can('wholesaler')
|
||||||
<div class="tab-pane fade" id="internal" role="tabpanel">
|
<div class="tab-pane fade" id="internal" role="tabpanel">
|
||||||
@include('a.service.widget.internal')
|
@include('a.service.widgets.internal')
|
||||||
</div>
|
</div>
|
||||||
@endcan
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
<!-- Show active services -->
|
||||||
|
<div class="card card-primary">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Active Services</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
@if ($o->services->count())
|
||||||
|
<table class="table table-striped table-hover" id="services_active">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Category</th>
|
||||||
|
<th>Service</th>
|
||||||
|
<th>Product</th>
|
||||||
|
<th>Next Invoice</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach ($o->services as $oo)
|
||||||
|
<tr>
|
||||||
|
<td><a href="{{ url('u/service',[$oo->id]) }}">{{ $oo->sid }}</a></td>
|
||||||
|
<td>{{ $oo->product_category }}</td>
|
||||||
|
<td>{{ $oo->name_short }}</td>
|
||||||
|
<td>{{ $oo->product_name }}</td>
|
||||||
|
<td>{{ $oo->external_billing ? '-' : $oo->next_invoice->format('Y-m-d') }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th>Count {{ $o->services->count() }}</th>
|
||||||
|
<th colspan="4"> </th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@else
|
||||||
|
<p>No services active</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@section('page-scripts')
|
||||||
|
@css('//cdn.datatables.net/1.10.25/css/dataTables.bootstrap5.min.css','jq-dt-css','jquery')
|
||||||
|
@js('//cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js','jq-dt-js','jquery')
|
||||||
|
@js('//cdn.datatables.net/1.10.25/js/dataTables.bootstrap5.min.js','jq-dt-bs5-js','jq-dt-js')
|
||||||
|
@js('//cdn.datatables.net/rowgroup/1.1.3/js/dataTables.rowGroup.min.js','jq-dt-rowgroup-js','jq-dt-js')
|
||||||
|
@css('//cdn.datatables.net/rowgroup/1.1.3/css/rowGroup.bootstrap5.min.css','jq-dt-rowgroup-css','jq-dt-jss')
|
||||||
|
|
||||||
|
<style>
|
||||||
|
table.dataTable tr.dtrg-group.dtrg-end.dtrg-level-0 {
|
||||||
|
font-size: 75%;
|
||||||
|
background-color: #eeeeee !important;
|
||||||
|
}
|
||||||
|
table.dataTable tr.dtrg-group.dtrg-end.dtrg-level-0 td {
|
||||||
|
background-color: #fefefe !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#services_active').DataTable( {
|
||||||
|
order: [4,'asc'],
|
||||||
|
rowGroup: {
|
||||||
|
dataSrc: 1,
|
||||||
|
endRender: function ( rows, group ) {
|
||||||
|
return rows.count()+' x ' + group;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#services_active tbody').on('click','tr', function () {
|
||||||
|
$(this).toggleClass('selected');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@append
|
@ -1,63 +0,0 @@
|
|||||||
@if(($x=$o->get())->count())
|
|
||||||
<table class="table table-bordered w-100" id="{{ $widget_invoice_name ?? 'widget-invoice'}}">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right">Account</th>
|
|
||||||
<th class="text-right">#</th>
|
|
||||||
<th class="text-right">Issued</th>
|
|
||||||
<th class="text-right">Due</th>
|
|
||||||
<th class="text-right">Total</th>
|
|
||||||
<th class="text-right">Payments</th>
|
|
||||||
<th class="text-right">Outstanding</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
@foreach ($x as $oo)
|
|
||||||
<tr>
|
|
||||||
<td id="account">{{ $oo->account->name }}</td>
|
|
||||||
<td class="text-right"><a href="{{ url('u/invoice',$oo->id) }}">{{ $oo->id }}</a></td>
|
|
||||||
<td class="text-right">{{ $oo->date_orig->format('Y-m-d') }}</td>
|
|
||||||
<td class="text-right">{{ $oo->due_date->format('Y-m-d') }}</td>
|
|
||||||
<td class="text-right">${{ number_format($oo->invoice_total,2) }}</td>
|
|
||||||
<td class="text-right">${{ number_format($oo->payments,2) }}</td>
|
|
||||||
<td class="text-right">${{ number_format($oo->balance,2) }}</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
@section('page-scripts')
|
|
||||||
@css('//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css','jq-dt-css','jquery')
|
|
||||||
@js('//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js','jq-dt-js','jquery')
|
|
||||||
@css('//cdn.datatables.net/responsive/2.2.1/css/responsive.dataTables.min.css','jq-dt-r-css','jq-dt-css')
|
|
||||||
@js('//cdn.datatables.net/responsive/2.2.1/js/dataTables.responsive.min.js','jq-dt-r-js','jq-dt-js')
|
|
||||||
@css('/plugin/dataTables/dataTables.bootstrap4.css','dt-bootstrap4-css','jq-dt-css')
|
|
||||||
@js('/plugin/dataTables/dataTables.bootstrap4.js','dt-bootstrap4-js','jq-dt-js')
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#{{ $widget_invoice_name ?? 'widget-invoice'}}').DataTable({
|
|
||||||
responsive: true,
|
|
||||||
order: [[0,'asc'],[3,'desc']],
|
|
||||||
rowGroup: {
|
|
||||||
dataSrc: 0,
|
|
||||||
},
|
|
||||||
columnDefs: [
|
|
||||||
{
|
|
||||||
targets: [0],
|
|
||||||
visible: false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#{{ $widget_invoice_name ?? 'widget-invoice'}} tbody').on('click','tr', function () {
|
|
||||||
$(this).toggleClass('selected');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@append
|
|
||||||
|
|
||||||
@else
|
|
||||||
No data to display
|
|
||||||
@endif
|
|
@ -1,53 +0,0 @@
|
|||||||
@if(($x=$o->get())->count())
|
|
||||||
<table class="table table-bordered w-100" id="{{ $widget_payment_name ?? 'widget-payment'}}">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="text-right">#</th>
|
|
||||||
<th class="text-right">Received</th>
|
|
||||||
<th class="text-right">Total</th>
|
|
||||||
{{--<th class="text-right">Balance</th>--}}
|
|
||||||
<th>Invoice(s)</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
@foreach ($x as $oo)
|
|
||||||
<tr>
|
|
||||||
<td class="text-right"><a href="{{ url('u/payment',$oo->id) }}">{{ $oo->id }}</a></td>
|
|
||||||
<td class="text-right">{{ $oo->date_payment->format('Y-m-d') }}</td>
|
|
||||||
<td class="text-right">${{ number_format($oo->total_amt,2) }}</td>
|
|
||||||
{{--<td class="text-right">${{ number_format($oo->balance,2) }}</td>--}}
|
|
||||||
<td>{!! join(',',$oo->items
|
|
||||||
->filter(function($item) { return $item->invoice_id; })
|
|
||||||
->transform(function($item) { return sprintf('<a href="%s">%s</a>',url('u/invoice',$item->invoice_id),$item->invoice_id); })
|
|
||||||
->toArray()) !!}</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
@section('page-scripts')
|
|
||||||
@css('//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css','jq-dt-css','jquery')
|
|
||||||
@js('//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js','jq-dt-js','jquery')
|
|
||||||
@css('//cdn.datatables.net/responsive/2.2.1/css/responsive.dataTables.min.css','jq-dt-r-css','jq-dt-css')
|
|
||||||
@js('//cdn.datatables.net/responsive/2.2.1/js/dataTables.responsive.min.js','jq-dt-r-js','jq-dt-js')
|
|
||||||
@css('/plugin/dataTables/dataTables.bootstrap4.css','dt-bootstrap4-css','jq-dt-css')
|
|
||||||
@js('/plugin/dataTables/dataTables.bootstrap4.js','dt-bootstrap4-js','jq-dt-js')
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#{{ $widget_payment_name ?? 'widget-payment'}}').DataTable({
|
|
||||||
responsive: true,
|
|
||||||
order: [1, 'desc']
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#{{ $widget_payment_name ?? 'widget-payment'}} tbody').on('click','tr', function () {
|
|
||||||
$(this).toggleClass('selected');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@append
|
|
||||||
|
|
||||||
@else
|
|
||||||
No data to display
|
|
||||||
@endif
|
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use App\Http\Controllers\ResellerServicesController;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
@ -13,23 +13,14 @@ use Illuminate\Http\Request;
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
Route::middleware('auth:api')->get('/user', function (Request $request) {
|
|
||||||
return $request->user();
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
Route::group(['middleware'=>['auth:api','role:reseller']], function() {
|
Route::group(['middleware'=>['auth:api','role:reseller']], function() {
|
||||||
Route::get('/r/agents','ResellerServicesController@agents');
|
Route::get('/r/agents','ResellerServicesController@agents');
|
||||||
Route::get('/r/accounts','ResellerServicesController@accounts');
|
Route::get('/r/accounts',[ResellerServicesController::class,'accounts']);
|
||||||
Route::get('/r/clients','ResellerServicesController@clients');
|
Route::get('/r/clients','ResellerServicesController@clients');
|
||||||
Route::get('/r/service_inactive','ResellerServicesController@service_inactive');
|
Route::get('/r/service_inactive','ResellerServicesController@service_inactive');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::group(['middleware'=>'auth:api'], function() {
|
Route::group(['middleware'=>'auth:api'], function() {
|
||||||
Route::get('/u/services/{o}','UserServicesController@services')
|
|
||||||
->where('o','[0-9]+')
|
|
||||||
->middleware('can:view,o');
|
|
||||||
Route::post('/u/checkout/fee/{o}','CheckoutController@fee')
|
Route::post('/u/checkout/fee/{o}','CheckoutController@fee')
|
||||||
->where('o','[0-9]+');
|
->where('o','[0-9]+');
|
||||||
});
|
});
|
@ -54,24 +54,24 @@ Route::group(['middleware'=>['theme:adminlte-be','auth','role:reseller'],'prefix
|
|||||||
// Our User Routes
|
// Our User Routes
|
||||||
Route::group(['middleware'=>['theme:adminlte-be','auth'],'prefix'=>'u'],function() {
|
Route::group(['middleware'=>['theme:adminlte-be','auth'],'prefix'=>'u'],function() {
|
||||||
Route::get('home',[HomeController::class,'home']);
|
Route::get('home',[HomeController::class,'home']);
|
||||||
Route::get('home/{o}','UserHomeController@home')
|
Route::get('home/{o}',[HomeController::class,'home'])
|
||||||
->where('o','[0-9]+')
|
->where('o','[0-9]+')
|
||||||
->middleware('can:view,o');
|
->middleware('can:view,o');
|
||||||
Route::get('account/{o}/invoice','User\AccountController@view_invoice_next')
|
Route::get('account/{o}/invoice','User\AccountController@view_invoice_next')
|
||||||
->where('o','[0-9]+')
|
->where('o','[0-9]+')
|
||||||
->middleware('can:view,o');
|
->middleware('can:view,o');
|
||||||
Route::post('checkout/pay','CheckoutController@pay');
|
Route::post('checkout/pay','CheckoutController@pay');
|
||||||
Route::get('invoice/{o}','UserHomeController@invoice')
|
Route::get('invoice/{o}',[HomeController::class,'invoice'])
|
||||||
|
->where('o','[0-9]+')
|
||||||
|
->middleware('can:view,o');
|
||||||
|
Route::get('invoice/{o}/pdf',[HomeController::class,'invoice_pdf'])
|
||||||
->where('o','[0-9]+')
|
->where('o','[0-9]+')
|
||||||
->middleware('can:view,o');
|
->middleware('can:view,o');
|
||||||
Route::get('invoice/cart','CheckoutController@cart_invoice');
|
Route::get('invoice/cart','CheckoutController@cart_invoice');
|
||||||
Route::get('invoice/cart/{o}','CheckoutController@cart_invoice')
|
Route::get('invoice/cart/{o}','CheckoutController@cart_invoice')
|
||||||
->where('o','[0-9]+')
|
->where('o','[0-9]+')
|
||||||
->middleware('can:view,o');
|
->middleware('can:view,o');
|
||||||
Route::get('invoice/{o}/pdf','UserHomeController@invoice_pdf')
|
Route::get('service/{o}',[HomeController::class,'service'])
|
||||||
->where('o','[0-9]+')
|
|
||||||
->middleware('can:view,o');
|
|
||||||
Route::get('service/{o}','UserHomeController@service')
|
|
||||||
->where('o','[0-9]+')
|
->where('o','[0-9]+')
|
||||||
->middleware('can:view,o');
|
->middleware('can:view,o');
|
||||||
Route::get('service/cancel/{o}','ServiceController@update')
|
Route::get('service/cancel/{o}','ServiceController@update')
|
||||||
@ -99,7 +99,6 @@ Route::group(['middleware'=>['theme:metronic-fe']],function() {
|
|||||||
Route::get('product_order/{o}','OrderController@product_order');
|
Route::get('product_order/{o}','OrderController@product_order');
|
||||||
Route::get('product_info/{o}','OrderController@product_info');
|
Route::get('product_info/{o}','OrderController@product_info');
|
||||||
Route::redirect('home','u/home');
|
Route::redirect('home','u/home');
|
||||||
Route::get('u/{type}/{action}/{id}','UserHomeController@oldsite');
|
|
||||||
|
|
||||||
Route::get('search','SearchController@search');
|
Route::get('search','SearchController@search');
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user