diff --git a/app/Http/Controllers/UserHomeController.php b/app/Http/Controllers/UserHomeController.php index 97772b7..936b5ba 100644 --- a/app/Http/Controllers/UserHomeController.php +++ b/app/Http/Controllers/UserHomeController.php @@ -3,10 +3,11 @@ namespace App\Http\Controllers; use Illuminate\Support\Facades\Auth; +use Illuminate\View\View; +use Barryvdh\Snappy\Facades\SnappyPdf as PDF; use App\Models\{Invoice,Service}; use App\User; -use PDF; class UserHomeController extends Controller { @@ -15,7 +16,12 @@ class UserHomeController extends Controller $this->middleware('auth'); } - public function home() + /** + * Logged in users home page + * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + */ + public function home(): View { switch (Auth::user()->role()) { case 'customer': @@ -32,11 +38,23 @@ class UserHomeController extends Controller } } - public function invoice(Invoice $o) + /** + * Render a specific invoice for the user + * + * @param Invoice $o + * @return View + */ + public function invoice(Invoice $o): View { return View('u.invoice',['o'=>$o]); } + /** + * Return the invoice in PDF format, ready to download + * + * @param Invoice $o + * @return mixed + */ public function invoice_pdf(Invoice $o) { return PDF::loadView('u.invoice', ['o'=>$o])->stream(sprintf('%s.pdf',$o->invoice_account_id)); @@ -56,8 +74,15 @@ class UserHomeController extends Controller abort(307,sprintf('http://www.graytech.net.au/u/%s/%s/%s',$type,$action,$id)); } - public function service(Service $o) + /** + * Return details on the users service + * + * @param Service $o + * @return View + */ + public function service(Service $o): View { + return View('u.service',['o'=>$o]); foreach ([ sprintf('u.service.%s.%s',$o->type->type,$o->status), sprintf('u.service.%s',$o->status), diff --git a/app/Interfaces/ServiceItem.php b/app/Interfaces/ServiceItem.php new file mode 100644 index 0000000..d15897a --- /dev/null +++ b/app/Interfaces/ServiceItem.php @@ -0,0 +1,20 @@ +'array', @@ -91,17 +96,27 @@ class Service extends Model /** * Account the service belongs to * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return BelongsTo */ public function account() { return $this->belongsTo(Account::class); } + /** + * Return automatic billing details + * + * @return HasOne + */ + public function billing() + { + return $this->hasOne(AccountBilling::class); + } + /** * Return Charges associated with this Service * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany */ public function charges() { @@ -146,10 +161,9 @@ class Service extends Model /** * Account that ordered the service * - * @todo changed to orderedby - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return BelongsTo */ - public function orderby() + public function orderedby() { return $this->belongsTo(Account::class); } @@ -157,30 +171,23 @@ class Service extends Model /** * Product of the service * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return BelongsTo */ public function product() { return $this->belongsTo(Product::class); } - /** - * Tenant that the service belongs to - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function site() - { - return $this->belongsTo(Site::class); - } - /** * Return a child model with details of the service * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo + * @return MorphTo */ public function type() { + if (! $this->model) + abort(500,'Missing Model in',['service'=>$this]); + return $this->morphTo(null,'model','id','service_id'); } @@ -192,7 +199,8 @@ class Service extends Model public function scopeActive($query) { return $query->where(function () use ($query) { - $query->where('active',TRUE)->orWhereNotIn('order_status',$this->inactive_status); + $query->where('active',TRUE) + ->orWhereNotIn('order_status',$this->inactive_status); }); } @@ -205,7 +213,8 @@ class Service extends Model public function scopeInActive($query) { return $query->where(function () use ($query) { - $query->where('active',FALSE)->orWhereIn('order_status',$this->inactive_status); + $query->where('active',FALSE) + ->orWhereIn('order_status',$this->inactive_status); }); } @@ -251,6 +260,16 @@ class Service extends Model return $this->getUrlAdminAttribute(); } + /** + * Return the auto billing details + * + * @return mixed + */ + public function getAutoPayAttribute() + { + return $this->billing; + } + public function getBillingPriceAttribute(): float { // @todo Temporary for services that dont have recur_schedule set. @@ -337,6 +356,7 @@ class Service extends Model * EG: * For ADSL, this would be the phone number, * For Hosting, this would be the domain name, etc + * @deprecated */ public function getNameShortAttribute() { @@ -372,6 +392,25 @@ class Service extends Model return $result; } + /** + * Work out when this service has been paid to. + * + * @todo This might need to be optimised + */ + public function getPaidToAttribute() + { + foreach ($this->invoices->reverse() as $o) { + if ($o->due == 0) { + return $o->items + ->filter(function($item) { + return $item->item_type === 0; + }) + ->last() + ->date_stop; + } + } + } + /** * Get the Product's Category for this service * @@ -392,9 +431,9 @@ class Service extends Model } /** - * @deprecated see getServiceIdAttribute() + * @deprecated see getSIDAttribute() */ - public function getServiceIdAttribute() + public function getServiceIdAttribute(): string { return $this->getSIDAttribute(); } @@ -425,6 +464,50 @@ class Service extends Model return sprintf('%02s-%04s.%05s',$this->site_id,$this->account_id,$this->id); } + /** + * Return the service description. + * For: + * + Broadband, this is the service address + * + Domains, blank + * + Hosting, blank + * + SSL, blank + * + * @return string + */ + public function getSDescAttribute(): string + { + return $this->type->service_description; + } + + /** + * Return the service name. + * For: + * + Broadband, this is the service number + * + Domains, this is the full domain name + * + Hosting, this is the full domain name + * + SSL, this is the DN + * + * @return string + */ + public function getSNameAttribute(): string + { + return $this->type->service_name; + } + + /** + * Return the service product type + * This is used for view specific details + * + * @return string + */ + public function getSTypeAttribute(): string + { + switch($this->product->model) { + case 'App\Models\Product\Adsl': return 'broadband'; + default: abort(500,'Product type not configured',['product'=>$this->product]); + } + } + /** * Return the Service Status * @@ -545,6 +628,16 @@ class Service extends Model return (! $this->external_billing) AND (! $this->suspend_billing) AND $this->getInvoiceNextAttribute()->lessThan(now()->addDays($days)); } + /** + * Identify if a service is being ordered + * + * @return bool + */ + public function isPending(): bool + { + return ! $this->active AND ! in_array($this->order_status,$this->inactive_status); + } + public function next_invoice_items(): \Illuminate\Support\Collection { $result = collect(); diff --git a/app/Models/Service/Adsl.php b/app/Models/Service/Adsl.php index b32198f..dca9b77 100644 --- a/app/Models/Service/Adsl.php +++ b/app/Models/Service/Adsl.php @@ -2,17 +2,35 @@ namespace App\Models\Service; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphOne; + +use App\Interfaces\ServiceItem; +use App\Models\Base\ServiceType; +use App\Models\Service; use App\Traits\NextKey; -class Adsl extends \App\Models\Base\ServiceType +class Adsl extends ServiceType implements ServiceItem { use NextKey; - const RECORD_ID = 'service__adsl'; // @todo column service_id can be removed. protected $table = 'ab_service__adsl'; - protected $dates = ['service_connect_date','service_contract_date']; + protected $dates = [ + 'service_connect_date', + 'service_contract_date' + ]; + + /** + * The service this belongs to + * + * @return BelongsTo|MorphOne + */ + public function service() + { + return $this->belongsTo(Service::class); + } /** SCOPES */ @@ -35,22 +53,41 @@ class Adsl extends \App\Models\Base\ServiceType /** ATTRIBUTES **/ /** - * @deprecated use getNameFullAttribute() + * @deprecated use $o->type()->service_name; + * @return mixed|string */ - public function getFullNameAttribute() - { - return $this->getNameFullAttribute(); - } - public function getNameAttribute() { return $this->service_number ?: $this->service_address; } - public function getNameFullAttribute() + /** + * Return the service address + * + * @return string + */ + public function getServiceDescriptionAttribute(): string { - return ($this->service_number AND $this->service_address) - ? sprintf('%s: %s',$this->service_number, $this->service_address) - : $this->name; + return $this->service_address ?: 'NO Service Address'; + } + + /** + * Return the service number + * + * @return string + */ + public function getServiceNameAttribute(): string + { + return $this->service_number ?: 'NO Service Number'; + } + + /** + * Is this service currently in a contract + * + * @return bool + */ + public function inContract(): bool + { + return $this->service_contract_date AND $this->service_contract_date->addMonths($this->contract_term)->isFuture(); } } \ No newline at end of file diff --git a/resources/theme/backend/adminlte/r/home.blade.php b/resources/theme/backend/adminlte/r/home.blade.php index bf3b1d1..898028a 100644 --- a/resources/theme/backend/adminlte/r/home.blade.php +++ b/resources/theme/backend/adminlte/r/home.blade.php @@ -3,11 +3,11 @@ @section('htmlheader_title') Reseller Home @endsection - -@section('contentheader_title') +@section('page_title') {{ $o->full_name }} @endsection -@section('page_title') + +@section('contentheader_title') {{ $o->full_name }} @endsection @section('contentheader_description') @@ -59,9 +59,6 @@
@include('r.agents')
-
- @include('r.service_inactive') -
@include('r.clients')
diff --git a/resources/theme/backend/adminlte/r/service_inactive.blade.php b/resources/theme/backend/adminlte/r/service_inactive.blade.php deleted file mode 100644 index 44a91da..0000000 --- a/resources/theme/backend/adminlte/r/service_inactive.blade.php +++ /dev/null @@ -1,87 +0,0 @@ -
-
-

Services Inactive

-
- - -
-
- -
- @if ($user->all_client_service_inactive()->count()) - - - - - - - - - - - - - - - - -
IDAccountNameStatusProduct
Count {{ $user->all_client_service_inactive()->count() }} 
- @else -

No Inactive Services

- @endif -
-
- -@section('page-scripts') - @css('https://cdn.datatables.net/responsive/2.2.1/css/responsive.dataTables.min.css') - @css('https://cdn.datatables.net/rowgroup/1.0.2/css/rowGroup.dataTables.min.css') - @js('https://cdn.datatables.net/responsive/2.2.1/js/dataTables.responsive.min.js') - @js('https://cdn.datatables.net/rowgroup/1.0.2/js/dataTables.rowGroup.min.js') - - - -@append \ No newline at end of file diff --git a/resources/theme/backend/adminlte/u/home.blade.php b/resources/theme/backend/adminlte/u/home.blade.php index cf359f3..3de3c0d 100644 --- a/resources/theme/backend/adminlte/u/home.blade.php +++ b/resources/theme/backend/adminlte/u/home.blade.php @@ -3,11 +3,11 @@ @section('htmlheader_title') Client Home @endsection - -@section('contentheader_title') +@section('page_title') {{ $o->full_name }} @endsection -@section('page_title') + +@section('contentheader_title') {{ $o->full_name }} @endsection @section('contentheader_description') diff --git a/resources/theme/backend/adminlte/u/service.blade.php b/resources/theme/backend/adminlte/u/service.blade.php index bb49010..e3c4636 100644 --- a/resources/theme/backend/adminlte/u/service.blade.php +++ b/resources/theme/backend/adminlte/u/service.blade.php @@ -1,38 +1,95 @@ @extends('adminlte::layouts.app') @section('htmlheader_title') - Service #{{ $o->id }} + {{ $o->sid }} +@endsection +@section('page_title') + {{ $o->sid }} @endsection @section('contentheader_title') - Service #{{ $o->id }} + Service: {{ $o->sid }} NBN-50/20-100 @endsection @section('contentheader_description') - {{ $o->service_id }} + {{ $o->sname }}: {{ $o->sdesc }} @endsection @section('main-content') -
-
-
-

Service Information

-
+
+ +
+ @include('u.service.widgets.'.$o->stype.'.details',['o'=>$o->type]) + @include('u.service.widgets.information') +
-
-
- @switch($o->order_status) - @case('ORDER-SUBMIT') - @case('ORDER-SENT') - @case('ORDER-HOLD') - @case('ORDERED') - @include('u.widgets.service.order.sent') - @break +
+
+
+ + - @default - @include('u.widgets.service.info') - @endswitch + +
+ +
+
+
+ Traffic. +
+
+ Product. +
+
+ Invoice Next. +
+
+ Invoices. +
+
+ Email. +
+
+
-@endsection \ No newline at end of file +@endsection + +@section('page-scripts') + +@append \ No newline at end of file diff --git a/resources/theme/backend/adminlte/u/service/adsl/ACTIVE.blade.php b/resources/theme/backend/adminlte/u/service/adsl/ACTIVE.blade.php deleted file mode 100644 index 3f7e3c2..0000000 --- a/resources/theme/backend/adminlte/u/service/adsl/ACTIVE.blade.php +++ /dev/null @@ -1,152 +0,0 @@ -@extends('adminlte::layouts.app') - -@section('htmlheader_title') - {{ $o->SID }} -@endsection - -@section('contentheader_title') - Service: {{ $o->SID }} -@endsection -@section('page_title') - {{ $o->SID }} -@endsection -@section('contentheader_description') - {{ $o->type->name_full }} -@endsection - -@section('main-content') -
-
-
-
-
- -
- -
-
-
-
- -
- @include('common.service.widget.info') - -
-
- Service Details -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Number{{ $o->type->service_number }}
Address{{ $o->type->service_address }}
Connected{{ $o->type->service_connect_date->format('Y-m-d') }}
Contract{{ $o->type->contract_term }} mths (until {{ $o->type->service_contract_date ? $o->type->service_contract_date->addMonths($o->type->contract_term)->format('Y-m-d') : 'N/A' }})
Username{{ $o->type->service_username }}
Password{{ $o->type->service_password }}
IP Address{{ $o->type->ipaddress ? $o->type->ipaddress : 'Dynamic' }}
-
-
- -
-
- DSL Details -
- -
- - - - - - @if ($o->product->type->base_down_peak) - - - - - @endif - @if ($o->product->type->base_down_offpeak) - - - - - @endif - - - - - - - - - - - - -
Speed{{ $o->product->type->speed }}
Peak Included Downloads{{ number_format($o->product->type->base_down_peak,0) }}GB
Peak Included Downloads{{ number_format($o->product->type->base_down_offpeak,0) }}MB
Traffic Last MonthTBA
Traffic This MonthTBA
Excess Traffic Charges to BillTBA
-
-
- -
-
-
- -
-
-
- @include('common.service.widget.invoice') - - {{-- @todo show list of outstanding invoices --}} -
- - {{-- Workaround since col-offset-x is not in our CSS? --}} -
-   -
- -
- @include('common.invoice.widget.list') -
-
-
- -
-
- -
-
-
-
-
-
- -
-
-@endsection \ No newline at end of file diff --git a/resources/theme/backend/adminlte/u/service/widgets/broadband/details.blade.php b/resources/theme/backend/adminlte/u/service/widgets/broadband/details.blade.php new file mode 100644 index 0000000..263c48f --- /dev/null +++ b/resources/theme/backend/adminlte/u/service/widgets/broadband/details.blade.php @@ -0,0 +1,70 @@ +
+ + @if($o->service->isPending()) +
+
+ Pending +
+
+ @endif + +
+

Broadband Details

+
+ +
+ + + + + + + + + + + + + + + + + + @if($o->service_connect_date) + + + + + @endif + + @if(FALSE) + + + + + + + + + @endif + + + + + @if ($o->inContract()) + + + + + + + + + @endif + + + + +
Address{{ $o->service_description }}
Service Number{{ $o->service_name }}
Service Username{{ $o->service_username }}
Service Password{{ $o->service_password }}
Connected{{ $o->service_connect_date->format('Y-m-d') }}
Speed{{ 'xxx/YY' }} Mbps
Traffic{{ 'xxx' }} GB (YY GB used month)
IP Address{{ $o->ipaddress ?: 'Dynamic' }}
Contract{{ $o->contract_term }} months ({{ ($x=$o->service_contract_date->addMonths($o->contract_term))->diffForHumans() }})
Contract End{{ $x->format('Y-m-d') }}
Cancel Notice1 month @if($o->inContract())(after {{ $o->service_contract_date->addMonths($o->contract_term-1)->format('Y-m-d') }})@endif
+
+
\ No newline at end of file diff --git a/resources/theme/backend/adminlte/u/service/widgets/information.blade.php b/resources/theme/backend/adminlte/u/service/widgets/information.blade.php new file mode 100644 index 0000000..98f4aeb --- /dev/null +++ b/resources/theme/backend/adminlte/u/service/widgets/information.blade.php @@ -0,0 +1,39 @@ +
+
+

Service Information

+
+
+ + + + + + @if ($o->active) + + + + + + + + + + + + + + + + + + + + + @endif + + + + +
Status{{ $o->status }}
Billed{{ $o->billing_period }}
Invoiced To{{ $o->invoice_to->format('Y-m-d') }}
Paid Until{{ $o->paid_to->format('Y-m-d') }}
Next Invoice{{ $o->invoice_next->format('Y-m-d') }}
Estimated Invoice${{ number_format($o->billing_price,2) }}
Payment Method@if ($o->autopay)Direct Debit @else Invoice @endif
+
+
\ No newline at end of file