Initial reseller domain report, enable editing domain service details
This commit is contained in:
parent
bc26f7b881
commit
b515a1edeb
@ -9,5 +9,5 @@ RUN export COMPOSER_HOME=/var/www/.composer \
|
||||
&& mv .env.example .env \
|
||||
&& FORCE_PERMS=1 NGINX_START=FALSE /sbin/init \
|
||||
&& chmod +x /var/www/html/artisan \
|
||||
&& touch .migrate \
|
||||
&& /var/www/html/artisan storage:link \
|
||||
&& rm -rf /var/www/.composer
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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';
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ use App\Traits\NextKey;
|
||||
* Services that belong to an account
|
||||
*
|
||||
* Attributes for services:
|
||||
* + 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
|
||||
*
|
||||
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -31,5 +31,9 @@ class AuthServiceProvider extends ServiceProvider
|
||||
Gate::define('wholesaler', function ($user) {
|
||||
return $user->isWholesaler();
|
||||
});
|
||||
|
||||
Gate::define('reseller', function ($user) {
|
||||
return $user->isReseller();
|
||||
});
|
||||
}
|
||||
}
|
25
app/Traits/ScopeServiceActive.php
Normal file
25
app/Traits/ScopeServiceActive.php
Normal 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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
21
app/Traits/ScopeServiceUserAuthorised.php
Normal file
21
app/Traits/ScopeServiceUserAuthorised.php
Normal 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());
|
||||
}
|
||||
}
|
@ -28,6 +28,6 @@ class ReworkAccount extends Migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//abort(500,'cant go back');
|
||||
abort(500,'cant go back');
|
||||
}
|
||||
}
|
||||
|
35
database/migrations/2021_07_09_141228_rework_domains.php
Normal file
35
database/migrations/2021_07_09_141228_rework_domains.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class ReworkDomains extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
DB::statement('ALTER TABLE ab_service__domain MODIFY COLUMN id INT auto_increment');
|
||||
DB::statement('ALTER TABLE ab_service__domain RENAME TO service_domains');
|
||||
|
||||
Schema::table('service_domains', function (Blueprint $table) {
|
||||
$table->renameColumn('registrar_type','registrar_account');
|
||||
$table->unique(['domain_name','domain_tld_id']);
|
||||
$table->dropColumn(['registrar_password','registrar_pending_transfer']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
abort(500,'cant go back');
|
||||
}
|
||||
}
|
10
public/css/custom.css
vendored
10
public/css/custom.css
vendored
@ -3,6 +3,14 @@ hr.d-print-block {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.table:not(.table-borderless) tbody tr:last-child th,
|
||||
.table:not(.table-borderless) tbody tr:last-child td {
|
||||
border-bottom: 2px solid #dee2e6;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.table:not(.table-borderless) tbody tr:last-child th,
|
||||
.table:not(.table-borderless) tbody tr:last-child td {
|
||||
border-bottom: 2px solid #dee2e6;
|
||||
}
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group has-validation">
|
||||
<label for="domain_name">Domain Name</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-globe-asia"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control col-9 text-right @error('service.domain_name') is-invalid @enderror" id="domain_name" name="service[domain_name]" placeholder="Domain Name..." value="{{ old('service.domain_name',$o->domain_name) }}" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">.</span>
|
||||
</div>
|
||||
<select class="form-control col-3" name="service[domain_tld_id]">
|
||||
@foreach(\App\Models\DomainTld::active()->orderBy('name')->get() as $oo)
|
||||
<option value="{{ $oo->id }}" @if($oo->id == $o->domain_tld_id)selected @endif>{{ $oo->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('service.domain_name')
|
||||
{{ $message }}
|
||||
@else
|
||||
Domain Name is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Licensed Domain Name.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-3">
|
||||
<div class="form-group has-validation">
|
||||
<label for="domain_expire">Expiry</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-calendar"></i></span>
|
||||
</div>
|
||||
<input type="date" class="form-control @error('service.domain_expire') is-invalid @enderror" id="domain_expire" name="service[domain_expire]" value="{{ old('service.domain_expire',$o->service_expire->format('Y-m-d')) }}" required>
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('service.domain_expire')
|
||||
{{ $message }}
|
||||
@else
|
||||
Domain Expiry is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Date Domain Expires.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group has-validation">
|
||||
<label for="domain_registrar_id">Registrar</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-handshake"></i></span>
|
||||
</div>
|
||||
<select class="form-control @error('service.domain_registrar_id') is-invalid @enderror" id="domain_registrar_id" name="service[domain_registrar_id]">
|
||||
<option></option>
|
||||
@foreach(\App\Models\DomainRegistrar::active()->orderBy('name')->get() as $oo)
|
||||
<option value="{{ $oo->id }}" @if($oo->id == $o->domain_registrar_id)selected @endif>{{ $oo->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('service.domain_registrar_id')
|
||||
{{ $message }}
|
||||
@else
|
||||
Domain Registrar is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Domain Name Registrar.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-3">
|
||||
<div class="form-group has-validation">
|
||||
<label for="registrar_account">Registrar Account</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-calendar"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control @error('service.registrar_account') is-invalid @enderror" id="registrar_account" name="service[registrar_account]" value="{{ old('service.registrar_account',$o->registrar_account) }}">
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('service.registrar_account')
|
||||
{{ $message }}
|
||||
@else
|
||||
Registrar Account ID is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Registrar Account ID.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group has-validation">
|
||||
<label for="registrar_ns">DNS Location</label>
|
||||
<div class="input-group flex-nowrap">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-project-diagram"></i></span>
|
||||
</div>
|
||||
<select class="form-control @error('service.registrar_ns') is-invalid @enderror" id="registrar_ns" name="service[registrar_ns]">
|
||||
@foreach(\App\Models\Service\Domain::select('registrar_ns')->distinct()->get() as $oo)
|
||||
<option value="{{ $oo->registrar_ns }}" @if($oo->registrar_ns == $o->registrar_ns)selected @endif>{{ $oo->registrar_ns }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('service.registrar_ns')
|
||||
{{ $message }}
|
||||
@else
|
||||
DNS Details is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Domain DNS details.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-3">
|
||||
<div class="form-group has-validation">
|
||||
<label for="registrar_username">Registrar Username</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-calendar"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control @error('service.registrar_username') is-invalid @enderror" id="registrar_username" name="service[registrar_username]" value="{{ old('service.registrar_username',$o->registrar_username) }}">
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('service.registrar_username')
|
||||
{{ $message }}
|
||||
@else
|
||||
Registrar Username is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Registrar Username ID.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section('page-scripts')
|
||||
@css('//cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css','s2-css')
|
||||
@js('//cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js','s2-js','jquery')
|
||||
|
||||
<style>
|
||||
.select2-selection.select2-selection--single {
|
||||
height: calc(2.25rem + 2px) !important;
|
||||
}
|
||||
.select2.select2-container.select2-container--default {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.select2.select2-container.select2-container--default .selection {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#registrar_ns').select2({
|
||||
dropdownAutoWidth: true,
|
||||
width: 'style',
|
||||
tags: true,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -0,0 +1,19 @@
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h4>Update Service details</h4>
|
||||
|
||||
<form class="g-0 needs-validation" method="POST" action="{{ url('a/service/edit',[ $o->id]) }}">
|
||||
@csrf
|
||||
|
||||
@includeIf('a.service.widgets.'.$o->stype.'.update',['o'=>$o->type])
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@can('wholesaler')
|
||||
<button type="submit" name="submit" class="btn btn-success mr-0 float-right">@if ($site->exists)Save @else Add @endif</button>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,91 @@
|
||||
@extends('adminlte::layouts.app')
|
||||
|
||||
@section('htmlheader_title')
|
||||
Domain Names
|
||||
@endsection
|
||||
@section('page_title')
|
||||
Domains
|
||||
@endsection
|
||||
|
||||
@section('contentheader_title')
|
||||
Domain Names
|
||||
@endsection
|
||||
@section('contentheader_description')
|
||||
Domain Names currently managed.
|
||||
@endsection
|
||||
|
||||
@section('main-content')
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card card-dark">
|
||||
<div class="card-body">
|
||||
<table class="table table-hover" id="service_domain">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Service ID</tH>
|
||||
<th>Account</th>
|
||||
<th>Domain</th>
|
||||
<th>Expires</th>
|
||||
<th>Registrar</th>
|
||||
<th>DNS Host</th>
|
||||
<th>Next Billed</th>
|
||||
<th>Price</th>
|
||||
<th>Term</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach ($o as $oo)
|
||||
<tr @if ($oo->service_expire->isPast()) class="table-danger" @endif>
|
||||
<td><a href="{{ url('u/service',[$oo->service_id]) }}">{{ $oo->service->sid }}</td>
|
||||
<td>{{ $oo->service->account->name }}</td>
|
||||
<td>{{ $oo->service_name }}</td>
|
||||
<td>{{ $oo->service_expire->format('Y-m-d') }}</td>
|
||||
<td>{{ $oo->registrar->name }}</td>
|
||||
<td>{{ $oo->registrar_ns }}</td>
|
||||
<td>@if ($oo->service->isBilled()) <span class="@if($oo->service->suspend_billing)strike @endif">{{ $oo->service->invoice_next->format('Y-m-d') }}</span> @else - @endif</td>
|
||||
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items(TRUE)->sum('total'),2) }}@else - @endif</td>
|
||||
<td>{{ $oo->service->billing_period }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('page-scripts')
|
||||
@css('//cdn.datatables.net/1.10.25/css/dataTables.bootstrap4.min.css','jq-dt-css')
|
||||
@js('//cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js','jq-dt-js')
|
||||
@js('//cdn.datatables.net/1.10.25/js/dataTables.bootstrap4.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.bootstrap4.min.css','jq-dt-rowgroup-css','jq-dt-jss')
|
||||
|
||||
<style>
|
||||
.strike {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#service_domain').DataTable({
|
||||
order: [[4,'asc'],[1,'asc'],[2,'desc']],
|
||||
rowGroup: {
|
||||
dataSrc: 4,
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: [4],
|
||||
visible: false,
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
$('#invoices_due tbody').on('click','tr', function () {
|
||||
$(this).toggleClass('selected');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -25,16 +25,16 @@
|
||||
<div class="col-7">
|
||||
<div class="card">
|
||||
<div class="card-header bg-dark d-flex p-0">
|
||||
<ul class="nav nav-pills p-2 w-100">
|
||||
<ul class="nav nav-pills w-100 p-2">
|
||||
{{--
|
||||
<li class="nav-item"><a class="nav-link active" href="#product" data-toggle="tab">Product</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#traffic" data-toggle="tab">Traffic</a></li>
|
||||
--}}
|
||||
@if (! $o->suspend_billing AND ! $o->external_billing)
|
||||
<li class="nav-item active"><a class="nav-link" href="#pending_items" data-toggle="tab">Pending Items</a></li>
|
||||
<li class="nav-item"><a class="nav-link {{ (! session()->has('service_update')) ? 'active' : '' }}" href="#pending_items" data-toggle="tab">Pending Items</a></li>
|
||||
@endif
|
||||
@if ($o->hasUsage())
|
||||
<li class="nav-item active"><a class="nav-link" href="#traffic" data-toggle="tab">Traffic</a></li>
|
||||
<li class="nav-item"><a class="nav-link {{ (! $o->isBilled && (! session()->has('service_update'))) ? 'active' : '' }}" href="#traffic" data-toggle="tab">Traffic</a></li>
|
||||
@endif
|
||||
|
||||
{{--
|
||||
@ -43,11 +43,13 @@
|
||||
--}}
|
||||
@can('wholesaler')
|
||||
<li class="nav-item ml-auto"><a class="nav-link" href="#internal" data-toggle="tab">Internal</a></li>
|
||||
<li class="nav-item"><a class="nav-link {{ session()->has('service_update') ? 'active' : '' }}" href="#update" data-toggle="tab">Update</a></li>
|
||||
@endcan
|
||||
</ul>
|
||||
|
||||
@can('update',$o)
|
||||
<ul class="nav nav-pills ml-auto p-2">
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
ACTION <span class="caret"></span>
|
||||
@ -69,12 +71,12 @@
|
||||
Product.
|
||||
</div>
|
||||
@if (! $o->suspend_billing AND ! $o->external_billing)
|
||||
<div class="tab-pane fade show active" id="pending_items" role="tabpanel">
|
||||
<div class="tab-pane fade {{ (! session()->has('service_update')) ? 'active show' : '' }}" id="pending_items" role="tabpanel">
|
||||
@include('common.service.widget.invoice')
|
||||
</div>
|
||||
@endif
|
||||
@if ($o->hasUsage())
|
||||
<div class="tab-pane fade show" id="traffic" role="tabpanel">
|
||||
<div class="tab-pane fade {{ (! $o->isBilled && (! session()->has('service_update'))) ? 'active show' : '' }}" id="traffic" role="tabpanel">
|
||||
@if ($o->type->usage(30)->count())
|
||||
@include('u.service.widgets.'.$o->stype.'.usagegraph',['o'=>$o->type])
|
||||
@endif
|
||||
@ -90,6 +92,10 @@
|
||||
<div class="tab-pane fade" id="internal" role="tabpanel">
|
||||
@include('a.service.widgets.internal')
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade {{ session()->has('service_update') ? 'active show' : '' }}" id="update" role="tabpanel">
|
||||
@include('a.service.widgets.update')
|
||||
</div>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
|
@ -63,3 +63,21 @@
|
||||
</ul>
|
||||
</li>
|
||||
@endcan
|
||||
|
||||
@can('reseller')
|
||||
<li class="nav-header">RESELLER</li>
|
||||
|
||||
<li class="nav-item has-treeview @if(preg_match('#^a/report/(domain)#',request()->path()))menu-open @else menu-closed @endif">
|
||||
<a href="#" class="nav-link @if(preg_match('#^a/report/(domain)#',request()->path())) active @endif">
|
||||
<i class="nav-icon fas fa-list"></i> <p>REPORT<i class="fas fa-angle-left right"></i></p>
|
||||
</a>
|
||||
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('r/report/domain') }}" class="nav-link @if(preg_match('#^r/report/domain#',request()->path()))active @endif">
|
||||
<i class="nav-icon fas fa-globe-asia"></i> <p>Domain Names</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@endcan
|
@ -16,10 +16,10 @@ use App\Http\Controllers\{AdminController,
|
||||
*/
|
||||
|
||||
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::class,'accounts']);
|
||||
Route::get('/r/clients','ResellerServicesController@clients');
|
||||
Route::get('/r/service_inactive','ResellerServicesController@service_inactive');
|
||||
// Route::get('/r/clients','ResellerServicesController@clients');
|
||||
// Route::get('/r/service_inactive','ResellerServicesController@service_inactive');
|
||||
Route::post('r/invoices/{o}',[AdminController::class,'pay_invoices'])
|
||||
->where('o','[0-9]+')
|
||||
->middleware(['theme:adminlte-be','role:wholesaler']);
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use Leenooks\Controllers\AdminController as LeenooksAdminController;
|
||||
use App\Http\Controllers\{AdminController,
|
||||
Auth\LoginController,
|
||||
CheckoutController,
|
||||
@ -8,6 +9,7 @@ use App\Http\Controllers\{AdminController,
|
||||
OrderController,
|
||||
PaypalController,
|
||||
SearchController,
|
||||
ServiceController,
|
||||
WelcomeController};
|
||||
|
||||
/*
|
||||
@ -25,10 +27,10 @@ Auth::routes();
|
||||
Route::get('/logout',[LoginController::class,'logout']);
|
||||
|
||||
Route::group(['middleware'=>['theme:adminlte-be']],function() {
|
||||
Route::get('auth/{socialProvider}','Auth\SocialLoginController@redirectToProvider');
|
||||
Route::get('auth/{socialProvider}/callback','Auth\SocialLoginController@handleProviderCallback');
|
||||
Route::get('auth/{socialProvider}/link','Auth\SocialLoginController@link');
|
||||
Route::post('auth/{socialProvider}/linkcomplete','Auth\SocialLoginController@linkcomplete');
|
||||
// Route::get('auth/{socialProvider}','Auth\SocialLoginController@redirectToProvider');
|
||||
// Route::get('auth/{socialProvider}/callback','Auth\SocialLoginController@handleProviderCallback');
|
||||
// Route::get('auth/{socialProvider}/link','Auth\SocialLoginController@link');
|
||||
// Route::post('auth/{socialProvider}/linkcomplete','Auth\SocialLoginController@linkcomplete');
|
||||
});
|
||||
|
||||
// Generic Image Renderer - Render images that we dont have with a generic image
|
||||
@ -37,25 +39,31 @@ Route::get('image/generic/{width}/{height}/{color}/{name?}',[MediaController::cl
|
||||
// Our Admin Routes
|
||||
Route::group(['middleware'=>['theme:adminlte-be','auth','role:wholesaler'],'prefix'=>'a'],function() {
|
||||
Route::match(['get','post'],'setup',[AdminController::class,'setup']);
|
||||
Route::get('service/{o}','AdminHomeController@service');
|
||||
Route::post('service/{o}','AdminHomeController@service_update');
|
||||
Route::get('report/products','Wholesale\ReportController@products');
|
||||
// Route::get('service/{o}','AdminHomeController@service');
|
||||
// Route::post('service/{o}','AdminHomeController@service_update');
|
||||
// Route::get('report/products','Wholesale\ReportController@products');
|
||||
Route::match(['get','post'],'payment/add',[AdminController::class,'pay_add']);
|
||||
|
||||
Route::post('service/edit/{o}',[ServiceController::class,'domain_edit'])
|
||||
->where('o','[0-9]+')
|
||||
->middleware('can:update,o');
|
||||
//Route::get('accounting/connect','AccountingController@connect');
|
||||
});
|
||||
|
||||
Route::get('admin/switch/stop','\Leenooks\Controllers\AdminController@user_switch_stop')->name('switch.user.start')->middleware('auth');
|
||||
Route::get('admin/switch/stop',[LeenooksAdminController::class,'user_switch_stop'])->name('switch.user.start')->middleware('auth');
|
||||
|
||||
// Our Reseller Routes
|
||||
Route::group(['middleware'=>['theme:adminlte-be','auth','role:reseller'],'prefix'=>'r'],function() {
|
||||
Route::get('supplier/index','SuppliersController@index');
|
||||
Route::get('supplier/create','SuppliersController@create');
|
||||
Route::post('supplier/store','SuppliersController@store');
|
||||
Route::get('switch/start/{id}','\Leenooks\Controllers\AdminController@user_switch_start')->name('switch.user.stop');
|
||||
Route::match(['get','post'],'service/update/{o}','ServiceController@update')
|
||||
->where('o','[0-9]+')
|
||||
->middleware('can:update,o');
|
||||
// Route::get('supplier/index','SuppliersController@index');
|
||||
// Route::get('supplier/create','SuppliersController@create');
|
||||
// Route::post('supplier/store','SuppliersController@store');
|
||||
Route::get('switch/start/{id}',[LeenooksAdminController::class,'user_switch_start'])->name('switch.user.stop');
|
||||
// Route::match(['get','post'],'service/update/{o}','ServiceController@update')
|
||||
// ->where('o','[0-9]+')
|
||||
// ->middleware('can:update,o');
|
||||
|
||||
Route::group(['middleware'=>['theme:adminlte-be','auth','role:reseller'],'prefix'=>'report'],function() {
|
||||
Route::get('domain',[ServiceController::class,'domain_list']);
|
||||
});
|
||||
});
|
||||
|
||||
// Our User Routes
|
||||
@ -64,9 +72,9 @@ Route::group(['middleware'=>['theme:adminlte-be','auth'],'prefix'=>'u'],function
|
||||
Route::get('home/{o}',[HomeController::class,'home'])
|
||||
->where('o','[0-9]+')
|
||||
->middleware('can:view,o');
|
||||
Route::get('account/{o}/invoice','User\AccountController@view_invoice_next')
|
||||
->where('o','[0-9]+')
|
||||
->middleware('can:view,o');
|
||||
// Route::get('account/{o}/invoice','User\AccountController@view_invoice_next')
|
||||
// ->where('o','[0-9]+')
|
||||
// ->middleware('can:view,o');
|
||||
Route::post('checkout/pay',[CheckoutController::class,'pay']);
|
||||
Route::get('invoice/{o}',[HomeController::class,'invoice'])
|
||||
->where('o','[0-9]+')
|
||||
@ -81,19 +89,19 @@ Route::group(['middleware'=>['theme:adminlte-be','auth'],'prefix'=>'u'],function
|
||||
Route::get('service/{o}',[HomeController::class,'service'])
|
||||
->where('o','[0-9]+')
|
||||
->middleware('can:view,o');
|
||||
Route::get('service/cancel/{o}','ServiceController@update')
|
||||
->where('o','[0-9]+')
|
||||
->middleware('can:update,o');
|
||||
Route::get('service/progress/{o}/{status}','UserHomeController@service_progress')
|
||||
->where('o','[0-9]+')
|
||||
->middleware('can:progress,o,status');
|
||||
// Route::get('service/cancel/{o}','ServiceController@update')
|
||||
// ->where('o','[0-9]+')
|
||||
// ->middleware('can:update,o');
|
||||
// Route::get('service/progress/{o}/{status}','UserHomeController@service_progress')
|
||||
// ->where('o','[0-9]+')
|
||||
// ->middleware('can:progress,o,status');
|
||||
});
|
||||
|
||||
// Doorman Code Routes
|
||||
Route::group(['middleware'=>['theme:adminlte-be'],'prefix'=>'u'],function() {
|
||||
Route::get('invoice/{o}/email/{code}','UserHomeController@invoice_pdf_email')
|
||||
->where('o','[0-9]+')
|
||||
->where('code','[0-9A-Z]{6}');
|
||||
// Route::get('invoice/{o}/email/{code}','UserHomeController@invoice_pdf_email')
|
||||
// ->where('o','[0-9]+')
|
||||
// ->where('code','[0-9A-Z]{6}');
|
||||
});
|
||||
|
||||
// Frontend Routes (Non-Authed Users)
|
||||
|
Loading…
Reference in New Issue
Block a user