From 6103b612657e65b34cd4978a0e1dfedcd1eef5c1 Mon Sep 17 00:00:00 2001 From: Deon George Date: Sat, 29 Jun 2019 10:14:12 +1000 Subject: [PATCH] Start of service display --- app/Http/Controllers/SearchController.php | 15 +- app/Http/Controllers/UserHomeController.php | 8 + app/Models/Account.php | 3 +- app/Models/Base/ServiceType.php | 26 ++++ app/Models/Product.php | 2 +- app/Models/Service.php | 138 +++++++++++++++--- app/Models/Service/Adsl.php | 35 ++++- app/Models/Site.php | 3 + app/User.php | 3 + .../common/invoice/widget/list.blade.php | 46 ++++++ .../common/service/widget/info.blade.php | 38 +++++ .../backend/adminlte/u/service.blade.php | 8 +- .../adminlte/u/service/adsl/ACTIVE.blade.php | 129 ++++++++++++++++ .../adminlte/u/widgets/service/info.blade.php | 5 +- 14 files changed, 426 insertions(+), 33 deletions(-) create mode 100644 resources/theme/backend/adminlte/common/invoice/widget/list.blade.php create mode 100644 resources/theme/backend/adminlte/common/service/widget/info.blade.php create mode 100644 resources/theme/backend/adminlte/u/service/adsl/ACTIVE.blade.php diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index 0ecd9cb..6c72a35 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -4,10 +4,8 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Log; -use App\Models\{Account}; +use App\Models\{Account,Service\Adsl}; class SearchController extends Controller { @@ -26,7 +24,7 @@ class SearchController extends Controller # Look for Account foreach (Account::Search($request->input('term')) - ->whereIN('id',$uo->all_clients()->pluck('id')) + ->whereIN('id',$uo->all_accounts()->pluck('id')) ->orderBy('company') ->orderBy('last_name') ->orderBy('first_name') @@ -35,6 +33,15 @@ class SearchController extends Controller $result->push(['label'=>sprintf('A:%s %s',$o->aid,$o->name),'value'=>'/u/account/'.$o->id]); } + # Look for an ADSL/NBN Service + foreach (Adsl::Search($request->input('term')) + ->whereIN('account_id',$uo->all_accounts()->pluck('id')) + ->orderBy('service_number') + ->limit(10)->get() as $o) + { + $result->push(['label'=>sprintf('S:%s (%s)',$o->name,$o->service->sid),'value'=>'/u/service/'.$o->id]); + } + return $result; } } \ No newline at end of file diff --git a/app/Http/Controllers/UserHomeController.php b/app/Http/Controllers/UserHomeController.php index 74df1f4..86929a2 100644 --- a/app/Http/Controllers/UserHomeController.php +++ b/app/Http/Controllers/UserHomeController.php @@ -57,6 +57,14 @@ class UserHomeController extends Controller public function service(Service $o) { + foreach ([ + sprintf('u.service.%s.%s',$o->type->type,$o->status), + sprintf('u.service.%s',$o->status), + ] as $v) + if (view()->exists($v)) + return View($v,['o'=>$o]); + + // View doesnt exist, fall back to default view return View('u.service',['o'=>$o]); } diff --git a/app/Models/Account.php b/app/Models/Account.php index 4aa5e72..b3c5be0 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -75,7 +75,8 @@ class Account extends Model /** * Search for a record * - * @param User $uo + * @param $query + * @param string $term * @return */ public function scopeSearch($query,string $term) diff --git a/app/Models/Base/ServiceType.php b/app/Models/Base/ServiceType.php index 0fd2060..e5a998c 100644 --- a/app/Models/Base/ServiceType.php +++ b/app/Models/Base/ServiceType.php @@ -4,6 +4,8 @@ namespace App\Models\Base; use Illuminate\Database\Eloquent\Model; +use App\Models\Service; + abstract class ServiceType extends Model { public $timestamps = FALSE; @@ -17,4 +19,28 @@ abstract class ServiceType extends Model { return $this->morphOne(Service::class,'type','model','id'); } + + /** SCOPES */ + + /** + * Search for a record + * + * @param $query + * @param string $term + * @return + */ + public function scopeSearch($query,string $term) + { + return $query + ->with(['service']) + ->join('ab_service','ab_service.id','=',$this->getTable().'.service_id') + ->Where('ab_service.id','like','%'.$term.'%'); + } + + /** ATTRIBUTES **/ + + public function getTypeAttribute() + { + return strtolower((new \ReflectionClass($this))->getShortName()); + } } \ No newline at end of file diff --git a/app/Models/Product.php b/app/Models/Product.php index 5b7a071..8691356 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -57,7 +57,7 @@ class Product extends Model private function getDefaultLanguage() { - return config('SITE_SETUP')->language; + return config('SITE_SETUP')->language(); } public function getDescriptionAttribute() diff --git a/app/Models/Service.php b/app/Models/Service.php index e8a7caf..bbfd26c 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -2,6 +2,8 @@ namespace App\Models; +use Carbon\Carbon; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; @@ -95,6 +97,37 @@ class Service extends Model return $this->belongsTo(Account::class); } + public function invoice_items($active=TRUE) + { + $query = $this->hasMany(InvoiceItem::class) + ->orderBy('date_orig'); + + if ($active) + $query->where('active','=',TRUE); + + return $query; + } + + /** + * Invoices for this service + * + */ + public function invoices($active=TRUE) + { + $query = $this->hasManyThrough(Invoice::class,InvoiceItem::class,NULL,'id',NULL,'invoice_id') + ->distinct('id') + ->where('ab_invoice.site_id','=',$this->site_id) + ->where('ab_invoice_item.site_id','=',$this->site_id) + ->orderBy('date_orig') + ->orderBy('due_date'); + + if ($active) + $query->where('ab_invoice_item.active','=',TRUE) + ->where('ab_invoice.active','=',TRUE); + + return $query; + } + /** * Account that ordered the service * @@ -105,16 +138,6 @@ class Service extends Model return $this->belongsTo(Account::class); } - /** - * Tenant that the service belongs to - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function site() - { - return $this->belongsTo(Site::class); - } - /** * Product of the service * @@ -125,6 +148,16 @@ class Service extends Model 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 * @@ -180,6 +213,25 @@ class Service extends Model return $this->getUrlAdminAttribute(); } + public function getBillingPriceAttribute(): float + { + if ($this->price) + return $this->addtax($this->price); + + dd($this->product->price_group,$this); + return $this->cost; + } + + /** + * Return the service billing period + * + * @return string + */ + public function getBillingPeriodAttribute(): string + { + return Arr::get($this->product->PricePeriods(),$this->recur_schedule,'Unknown'); + } + /** * Date the service expires, also represents when it is paid up to * @@ -191,23 +243,24 @@ class Service extends Model } /** - * Services Unique Identifier + * Return the date for the next invoice * - * @return string + * @todo This function negates the need for date_next_invoice + * @return null */ - public function getSIDAttribute(): string + public function getInvoiceNextAttribute(): Carbon { - return sprintf('%02s-%04s.%05s',$this->site_id,$this->account_id,$this->id); + $last = $this->getInvoiceToAttribute(); + + return $last ? $last->addDay() : now(); } /** - * Return the date for the next invoice - * - * @return null + * Get the date that the service has been invoiced to */ - public function getInvoiceNextAttribute() + public function getInvoiceToAttribute() { - return $this->date_next_invoice ? $this->date_next_invoice->format('Y-m-d') : NULL; + return $this->invoice_items->count() ? $this->invoice_items->last()->date_stop : NULL; } /** @@ -294,6 +347,16 @@ class Service extends Model return $this->getSIDAttribute(); } + /** + * Services Unique Identifier + * + * @return string + */ + public function getSIDAttribute(): string + { + return sprintf('%02s-%04s.%05s',$this->site_id,$this->account_id,$this->id); + } + /** * Return the Service Status * @@ -319,6 +382,24 @@ class Service extends Model : ''; } + /** + * Return a HTML status box + * + * @return string + */ + public function getStatusHTMLAttribute(): string + { + $class = NULL; + switch ($this->status) + { + case 'ACTIVE': + $class = 'badge-success'; + break; + } + + return sprintf('%s',$class,$this->status); + } + /** * URL used by an admin to administer the record * @@ -353,6 +434,25 @@ class Service extends Model /** FUNCTIONS **/ + /** + * Add applicable tax to the cost + * + * @todo This needs to be calculated, not fixed at 1.1 + * @param float $value + * @return float + */ + public function addTax(float $value): float + { + return round($value*1.1,2); + } + + public function invoices_due(): Collection + { + return $this->invoice_items->filter(function($item) { + return $item->invoice->due > 0; + }); + } + /** * Determine if a service is active. It is active, if active=1, or the order_status is not in inactive_status[] * diff --git a/app/Models/Service/Adsl.php b/app/Models/Service/Adsl.php index 9ad4cf6..b32198f 100644 --- a/app/Models/Service/Adsl.php +++ b/app/Models/Service/Adsl.php @@ -12,16 +12,45 @@ class Adsl extends \App\Models\Base\ServiceType // @todo column service_id can be removed. protected $table = 'ab_service__adsl'; + protected $dates = ['service_connect_date','service_contract_date']; + /** SCOPES */ + + /** + * Search for a record + * + * @param $query + * @param string $term + * @return + */ + public function scopeSearch($query,string $term) + { + // Build our where clause + return parent::scopeSearch($query,$term) + ->orwhere('service_number','like','%'.$term.'%') + ->orWhere('service_address','like','%'.$term.'%') + ->orWhere('ipaddress','like','%'.$term.'%'); + } + + /** ATTRIBUTES **/ + + /** + * @deprecated use getNameFullAttribute() + */ public function getFullNameAttribute() { - return ($this->service_number AND $this->service_address) - ? sprintf('%s: %s',$this->service_number, $this->service_address) - : $this->name; + return $this->getNameFullAttribute(); } public function getNameAttribute() { return $this->service_number ?: $this->service_address; } + + public function getNameFullAttribute() + { + return ($this->service_number AND $this->service_address) + ? sprintf('%s: %s',$this->service_number, $this->service_address) + : $this->name; + } } \ No newline at end of file diff --git a/app/Models/Site.php b/app/Models/Site.php index 975b406..20cdf00 100644 --- a/app/Models/Site.php +++ b/app/Models/Site.php @@ -23,6 +23,9 @@ class Site extends Model public function language() { + if (! $this->id) + return Language::find(1); + return $this->belongsTo(Language::class); } diff --git a/app/User.php b/app/User.php index bcc1da5..cb8a5ab 100644 --- a/app/User.php +++ b/app/User.php @@ -225,6 +225,9 @@ class User extends Authenticatable $result->push($o->accounts->where('active',TRUE)); } + // Include my accounts + $result->push($this->accounts); + return $result->flatten(); } diff --git a/resources/theme/backend/adminlte/common/invoice/widget/list.blade.php b/resources/theme/backend/adminlte/common/invoice/widget/list.blade.php new file mode 100644 index 0000000..ebfa1e3 --- /dev/null +++ b/resources/theme/backend/adminlte/common/invoice/widget/list.blade.php @@ -0,0 +1,46 @@ + + + + + + + + + + + + + @foreach ($o->invoices as $io) + + + + + + + + + @endforeach + +
#IssuedDueTotalPaymentsOutstanding
{{ $io->id }}{{ $io->date_orig->format('Y-m-d') }}{{ $io->due_date->format('Y-m-d') }}${{ number_format($io->total,2) }}${{ number_format($io->paid,2) }}${{ number_format($io->due,2) }}
+ +@section('page-scripts') + @css('https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css','jq-dt-css','jquery'); + @js('https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js','jq-dt-js','jquery'); + @css('https://cdn.datatables.net/responsive/2.2.1/css/responsive.dataTables.min.css','jq-dt-r-css','jq-dt-css') + @js('https://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') + + +@append \ No newline at end of file diff --git a/resources/theme/backend/adminlte/common/service/widget/info.blade.php b/resources/theme/backend/adminlte/common/service/widget/info.blade.php new file mode 100644 index 0000000..a4a3736 --- /dev/null +++ b/resources/theme/backend/adminlte/common/service/widget/info.blade.php @@ -0,0 +1,38 @@ +
+
+ Service Information +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Account{{ $o->account->name }}
Active{!! $o->status_html !!}
Billing Period{{ $o->billing_period }}
Billing Amount${{ number_format($o->billing_price,2) }}
Invoiced To{{ $o->invoice_to ? $o->invoice_to->format('Y-m-d') : '' }}
Next Invoice{{ $o->invoice_next ? $o->invoice_next->format('Y-m-d') : '' }}
Current Invoices Due${{ number_format($o->invoices_due()->sum('due'),2) }} ({{ $o->invoices_due()->count() }})
+
+
\ No newline at end of file diff --git a/resources/theme/backend/adminlte/u/service.blade.php b/resources/theme/backend/adminlte/u/service.blade.php index 3f5cce0..bb49010 100644 --- a/resources/theme/backend/adminlte/u/service.blade.php +++ b/resources/theme/backend/adminlte/u/service.blade.php @@ -5,7 +5,7 @@ @endsection @section('contentheader_title') - Service # + Service #{{ $o->id }} @endsection @section('contentheader_description') {{ $o->service_id }} @@ -14,11 +14,11 @@ @section('main-content')
-
-

Service Information

+
+

Service Information

-
+
@switch($o->order_status) @case('ORDER-SUBMIT') diff --git a/resources/theme/backend/adminlte/u/service/adsl/ACTIVE.blade.php b/resources/theme/backend/adminlte/u/service/adsl/ACTIVE.blade.php new file mode 100644 index 0000000..b2a74f2 --- /dev/null +++ b/resources/theme/backend/adminlte/u/service/adsl/ACTIVE.blade.php @@ -0,0 +1,129 @@ +@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 +
+ +
+ + + + + + + + + + + + + + + + + + + + + +
SpeedTBA
Peak Included DownloadsTBA
Traffic Last MonthTBA
Traffic This MonthTBA
Excess Traffic Charges to BillTBA
+
+
+ +
+
+
+ +
+ @include('common.invoice.widget.list') +
+ +
+
+ +
+
+
+
+
+
+ +
+
+@endsection \ No newline at end of file diff --git a/resources/theme/backend/adminlte/u/widgets/service/info.blade.php b/resources/theme/backend/adminlte/u/widgets/service/info.blade.php index 3df4160..cd25165 100644 --- a/resources/theme/backend/adminlte/u/widgets/service/info.blade.php +++ b/resources/theme/backend/adminlte/u/widgets/service/info.blade.php @@ -15,7 +15,10 @@ Account{{ $o->account->company }} - Active{{ $o->active }} ({{ $o->order_status }}) + Active{{ $o->active }} ({{ $o->order_status }}) [{{ $o->status }}] + + + Type{{ $o->type->type }} Product{{ $o->product->name }}: {{ $o->name }}