Initial reseller domain report, enable editing domain service details

This commit is contained in:
Deon George
2021-07-13 12:31:56 +10:00
parent bc26f7b881
commit b515a1edeb
26 changed files with 652 additions and 56 deletions

View File

@@ -72,6 +72,15 @@ class SearchController extends Controller
$result->push(['name'=>sprintf('%s (%s)',$o->name,$o->service->sid),'value'=>'/u/service/'.$o->id,'category'=>'Broadband']);
}
# Look for Domain Name
foreach (Service\Domain::Search($request->input('term'))
->whereIN('account_id',$accounts)
->orderBy('domain_name')
->limit(10)->get() as $o)
{
$result->push(['name'=>sprintf('%s (%s)',$o->service_name,$o->service->sid),'value'=>'/u/service/'.$o->id,'category'=>'Domains']);
}
return $result;
}
}

View File

@@ -3,18 +3,64 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
use App\Models\Service;
class ServiceController extends Controller
{
/**
* Edit a domain service details
*
* @param Request $request
* @param Service $o
* @return \Illuminate\Http\RedirectResponse
*/
public function domain_edit(Request $request,Service $o)
{
session()->flash('service_update',TRUE);
$validation = $request->validate([
'service.domain_name' => sprintf('required|unique:%s,domain_name,%d',$o->type->getTable(),$o->type->id),
'service.domain_expire' => 'required|date',
'service.domain_tld_id' => 'required|exists:ab_domain_tld,id',
'service.domain_registrar_id' => 'required|exists:ab_domain_registrar,id',
'service.registrar_account' => 'required',
'service.registrar_username' => 'required|string|min:5',
'service.registrar_ns' => 'required|string|min:5',
]);
$o->type->forceFill($validation['service'])->save();
return redirect()->back()->with('success','Record updated.');
}
/**
* List all the domains managed by the user
*
* @return View
*/
public function domain_list(): View
{
$o = Service\Domain::serviceActive()
->serviceUserAuthorised(Auth::user())
->select('service_domains.*')
->join('ab_service',['ab_service.id'=>'service_domains.service_id'])
->with(['service.account','registrar'])
->get();
return view('r.service.domain.list')
->with('o',$o);
}
/**
* Update a service
*
* @note: Route Middleware protects this path
* @param Request $request
* @param Service $o
* @return View|void
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
*/
public function update(Request $request,Service $o)
{

View File

@@ -2,6 +2,8 @@
namespace App\Interfaces;
use Carbon\Carbon;
interface ServiceItem
{
/**
@@ -11,6 +13,11 @@ interface ServiceItem
*/
public function getServiceDescriptionAttribute(): string;
/**
* Date the service expires
*/
public function getServiceExpireAttribute(): Carbon;
/**
* Return the Service Name.
*

View File

@@ -3,8 +3,11 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Leenooks\Traits\ScopeActive;
class DomainRegistrar extends Model
{
use ScopeActive;
protected $table = 'ab_domain_registrar';
}

View File

@@ -3,13 +3,25 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Leenooks\Traits\ScopeActive;
class DomainTld extends Model
{
use ScopeActive;
protected $table = 'ab_domain_tld';
/* RELATIONS */
public function services()
{
return $this->hasMany(Service::class);
}
/* ATTRIBUTES */
public function getNameAttribute($value): string
{
return strtoupper($value);
}
}

View File

@@ -24,8 +24,9 @@ use App\Traits\NextKey;
* 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
* + billing_period : The period that this service is billed for by default
* + name_short : Service Product short name, eg: phone number, domain name, certificate CN
* + sid : System ID for service
*
* @package App\Models
*/
@@ -89,12 +90,19 @@ class Service extends Model implements IDs
'type',
];
// @todo Change to self::INACTIVE_STATUS
private $inactive_status = [
'CANCELLED',
'ORDER-REJECTED',
'ORDER-CANCELLED',
];
public const INACTIVE_STATUS = [
'CANCELLED',
'ORDER-REJECTED',
'ORDER-CANCELLED',
];
/**
* Valid status shows the applicable next status for an action on a service
* Each status can be
@@ -362,6 +370,15 @@ class Service extends Model implements IDs
});
}
/**
* Only query records that the user is authorised to see
*/
public function scopeAuthorised($query,User $uo)
{
return $query
->whereIN($this->getTable().'.account_id',$uo->all_accounts()->pluck('id')->unique()->toArray());
}
/**
* Find inactive services.
*
@@ -1192,10 +1209,21 @@ class Service extends Model implements IDs
return $this->active OR ($this->order_status AND ! in_array($this->order_status,$this->inactive_status));
}
/**
* Do we bill for this service
*
* @return bool
*/
public function isBilled(): bool
{
return ! ($this->external_billing && $this->suspend_billing);
}
/**
* Should this service be invoiced soon
*
* @todo get the number of days from account setup
* @todo Use self::isBilled();
* @return bool
*/
public function isInvoiceDueSoon($days=30): bool
@@ -1221,6 +1249,7 @@ class Service extends Model implements IDs
* @param bool $future Next item to be billed (not in the next x days)
* @return Collection
* @throws Exception
* @todo Use self::isBilled();
*/
public function next_invoice_items(bool $future,Carbon $billdate=NULL): Collection
{

View File

@@ -92,6 +92,11 @@ class Adsl extends ServiceType implements ServiceItem,ServiceUsage
return strtoupper($this->service_address) ?: 'NO Service Address';
}
public function getServiceExpireAttribute(): \Carbon\Carbon
{
// TODO: Implement getServiceExpireAttribute() method.
}
/**
* Return the service number
*

View File

@@ -2,23 +2,41 @@
namespace App\Models\Service;
use App\Models\Base\ServiceType;
use App\Models\DomainRegistrar;
use App\Models\DomainTld;
use App\Interfaces\ServiceItem;
use App\Traits\NextKey;
use Carbon\Carbon;
use App\Models\Base\ServiceType;
use App\Models\{Account,DomainRegistrar,DomainTld,Service};
use App\Interfaces\ServiceItem;
use App\Traits\{NextKey,ScopeServiceActive,ScopeServiceUserAuthorised};
/**
* Class Domain (Service)
* Services that domain names
*
* Attributes for services:
* + service_description : Description as shown in a Service Context
* + service_expire : The date the service expires
* + service_name : Name as shown in a Service Context
*
* @package App\Models\Service
*/
class Domain extends ServiceType implements ServiceItem
{
use NextKey;
const RECORD_ID = 'service__domain';
use ScopeServiceActive,ScopeServiceUserAuthorised;
protected $dates = [
'domain_expire',
];
protected $table = 'ab_service__domain';
protected $table = 'service_domains';
protected $with = ['tld'];
/* RELATIONS */
public function account()
{
return $this->hasOneThrough(Account::class,Service::class);
}
public function registrar()
{
return $this->belongsTo(DomainRegistrar::class,'domain_registrar_id');
@@ -29,15 +47,46 @@ class Domain extends ServiceType implements ServiceItem
return $this->belongsTo(DomainTld::class,'domain_tld_id');
}
/* SCOPES */
/**
* Search for a record
*
* @param $query
* @param string $term
* @return mixed
*/
public function scopeSearch($query,string $term)
{
// If we have a period in the name, we'll ignore everything after it.
$term = strstr($term,'.',TRUE) ?: $term;
// Build our where clause
return parent::scopeSearch($query,$term)
->orwhere('domain_name','like','%'.$term.'%');
}
/* ATTRIBUTES */
public function getServiceDescriptionAttribute(): string
{
// N/A
return 'Domain Name';
}
public function getServiceExpireAttribute(): Carbon
{
return $this->domain_expire;
}
/**
* The name of the domain with its TLD
*
* @return string
*/
public function getServiceNameAttribute(): string
{
return sprintf('%s.%s',strtoupper($this->domain_name),strtoupper($this->tld->name));
return strtoupper(sprintf('%s.%s',$this->domain_name,$this->tld->name));
}
public function inContract(): bool

View File

@@ -7,6 +7,7 @@ use App\Models\Base\ServiceType;
use App\Models\DomainTld;
use App\Models\HostServer;
use App\Traits\NextKey;
use Carbon\Carbon;
class Host extends ServiceType implements ServiceItem
{
@@ -34,6 +35,11 @@ class Host extends ServiceType implements ServiceItem
return 'Hosting';
}
public function getServiceExpireAttribute(): Carbon
{
// TODO: Implement getServiceExpireAttribute() method.
}
public function getServiceNameAttribute(): string
{
return sprintf('%s.%s',strtoupper($this->domain_name),strtoupper($this->tld->name));

View File

@@ -58,6 +58,11 @@ class SSL extends ServiceType implements ServiceItem
}
}
public function getServiceExpireAttribute(): Carbon
{
// TODO: Implement getServiceExpireAttribute() method.
}
public function getServiceNameAttribute(): string
{
return $this->cert

View File

@@ -5,6 +5,7 @@ namespace App\Models\Service;
use App\Interfaces\ServiceItem;
use App\Models\Base\ServiceType;
use App\Traits\NextKey;
use Carbon\Carbon;
class Voip extends ServiceType implements ServiceItem
{
@@ -27,6 +28,11 @@ class Voip extends ServiceType implements ServiceItem
return $this->service_address ?: 'VOIP';
}
public function getServiceExpireAttribute(): Carbon
{
// TODO: Implement getServiceExpireAttribute() method.
}
/**
* Return the service number
*

View File

@@ -74,6 +74,8 @@ class User extends Authenticatable
'customer',
];
/* RELATIONS */
/**
* The accounts that this user manages
*
@@ -175,7 +177,7 @@ class User extends Authenticatable
return $this->hasMany(static::class,'parent_id','id');
}
/** ATTRIBUTES **/
/* ATTRIBUTES */
public function getActiveDisplayAttribute($value)
{
@@ -268,6 +270,8 @@ class User extends Authenticatable
return sprintf('<a href="/u/account/view/%s">%s</a>',$this->id,$this->user_id);
}
/* METHODS */
/**
* Users password reset email notification
*
@@ -278,7 +282,7 @@ class User extends Authenticatable
$this->notify((new ResetPasswordNotification($token))->onQueue('high'));
}
/** SCOPES */
/* SCOPES */
// @todo use trait
public function scopeActive()
@@ -323,6 +327,8 @@ class User extends Authenticatable
return $query;
}
/* GENERAL METHODS */
/**
* Determine if the user is an admin of the account with $id
*
@@ -334,8 +340,6 @@ class User extends Authenticatable
return $id AND $this->isReseller() AND in_array($id,$this->all_accounts()->pluck('id')->toArray());
}
/** FUNCTIONS */
/**
* Get a list of accounts for the clients of this user
*
@@ -437,8 +441,8 @@ class User extends Authenticatable
public function client_service_movements(): DatabaseCollection
{
return Service::active()
->authorised($this)
->where('order_status','!=','ACTIVE')
->whereIN('account_id',$this->all_accounts()->pluck('id')->unique()->toArray())
->with(['account','product'])
->get();
}
@@ -630,6 +634,14 @@ class User extends Authenticatable
->from($payment,'summary');
}
/**
* Determine what the logged in user's role is
* + Wholesaler - aka Super User
* + Reseller - services accounts on behalf of their customers
* + Customer - end user customer
*
* @return string
*/
public function role()
{
// If I have agents and no parent, I am the wholesaler

View File

@@ -31,5 +31,9 @@ class AuthServiceProvider extends ServiceProvider
Gate::define('wholesaler', function ($user) {
return $user->isWholesaler();
});
Gate::define('reseller', function ($user) {
return $user->isReseller();
});
}
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* Add a ScopeActive to an Eloquent Model to only show active services (including those soon to be active)
*/
namespace App\Traits;
use App\Models\Service;
trait ScopeServiceActive
{
/**
* Only query active service records
*/
public function scopeServiceActive($query)
{
return $query->where(function($q) {
return $q->where('ab_service.active',TRUE)
->orWhere(function($q) {
return $q->whereNotNull('order_status')
->whereNotIn('ab_service.order_status',Service::INACTIVE_STATUS);
});
});
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* Add a ScopeAuthorised to an Eloquent Model
* This will help limit the scope of accounts that a user can see.
*/
namespace App\Traits;
use App\Models\User;
trait ScopeServiceUserAuthorised
{
/**
* Only query records that the user is authorised to see
*/
public function scopeServiceUserAuthorised($query,User $uo)
{
return $query
->whereIN('ab_service.account_id',$uo->all_accounts()->pluck('id')->unique()->toArray());
}
}