Compare commits
5 Commits
078dc6ab39
...
2e9f87550c
Author | SHA1 | Date | |
---|---|---|---|
2e9f87550c | |||
78a8f63ac9 | |||
df3f7e31be | |||
0469d64577 | |||
f8453ae391 |
@ -6,17 +6,20 @@ use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
use App\Mail\TestEmail as MailTest;
|
||||
use App\Mail\Test;
|
||||
use App\Models\{Site,User};
|
||||
|
||||
class TestEmail extends Command
|
||||
class EmailTest extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'test:email {site : Site ID} {id : User ID} {email? : Alternative Email}';
|
||||
protected $signature = 'test-email'
|
||||
.' {--s|site : Site ID}'
|
||||
.' {id : User ID}'
|
||||
.' {email? : Alternative Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -25,16 +28,6 @@ class TestEmail extends Command
|
||||
*/
|
||||
protected $description = 'Send a test email';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
@ -42,11 +35,20 @@ class TestEmail extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Config::set('site',Site::findOrFail($this->argument('site')));
|
||||
Config::set(
|
||||
'site',
|
||||
$this->option('site')
|
||||
? Site::findOrFail($this->option('site'))
|
||||
: Site::where('url',config('app.url'))->sole()
|
||||
);
|
||||
|
||||
$uo = User::find($this->argument('id'));
|
||||
|
||||
Mail::to($this->argument('email') ?? $uo->email)
|
||||
->send(new MailTest($uo));
|
||||
$result = Mail::to($this->argument('email') ?? $uo->email)
|
||||
->send(new Test($uo));
|
||||
|
||||
$this->info($result->getMessageId());
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use App\Models\{Invoice,Site};
|
||||
@ -15,7 +14,9 @@ class InvoiceEmail extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'invoice:email {site} {id}';
|
||||
protected $signature = 'invoice:email'
|
||||
.' {--s|site : Site ID}'
|
||||
.' {id?}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -31,21 +32,23 @@ class InvoiceEmail extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Config::set('site',Site::findOrFail($this->argument('site')));
|
||||
Config::set(
|
||||
'site',
|
||||
$this->option('site')
|
||||
? Site::findOrFail($this->option('site'))
|
||||
: Site::where('url',config('app.url'))->sole()
|
||||
);
|
||||
|
||||
$o = Invoice::findOrFail($this->argument('id'));
|
||||
|
||||
$result = Mail::to($o->account->user->email)->send(new \App\Mail\InvoiceEmail($o));
|
||||
|
||||
try {
|
||||
$o->print_status = TRUE;
|
||||
//$o->reminders = $o->reminders('send');
|
||||
$o->send();
|
||||
$o->save();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
dd($e);
|
||||
}
|
||||
|
||||
dump($result->getDebug());
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
@ -14,7 +15,11 @@ class InvoiceGenerate extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'invoice:generate {site} {account?} {--p|preview : Preview} {--l|list : List Items}';
|
||||
protected $signature = 'invoice:generate'
|
||||
.' {--l|list : List Items}'
|
||||
.' {--p|preview : Preview}'
|
||||
.' {--s|site : Site ID}'
|
||||
.' {id?}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -30,37 +35,50 @@ class InvoiceGenerate extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Config::set('site',Site::findOrFail($this->argument('site')));
|
||||
Config::set(
|
||||
'site',
|
||||
$this->option('site')
|
||||
? Site::findOrFail($this->option('site'))
|
||||
: Site::where('url',config('app.url'))->sole()
|
||||
);
|
||||
|
||||
if ($this->argument('account'))
|
||||
$accounts = collect()->push(Account::find($this->argument('account')));
|
||||
if ($this->argument('id'))
|
||||
$accounts = collect()->push(Account::find($this->argument('id')));
|
||||
else
|
||||
$accounts = Account::active()->get();
|
||||
|
||||
foreach ($accounts as $o) {
|
||||
$items = $o->invoice_next(Carbon::now());
|
||||
|
||||
if (! $items->count()) {
|
||||
$this->warn(sprintf('No items for account (%s) [%d]',$o->name,$o->id));
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->info(sprintf('Account: %s [%d]',$o->name,$o->lid));
|
||||
$io = new Invoice;
|
||||
$io->account_id = $o->id;
|
||||
|
||||
foreach ($o->services(TRUE)->get() as $so) {
|
||||
foreach ($so->next_invoice_items(FALSE) as $ooo)
|
||||
$io->items->push($ooo);
|
||||
}
|
||||
foreach ($items as $oo)
|
||||
$io->items_active->push($oo);
|
||||
|
||||
// If there are no items, no reason to do anything
|
||||
if (! $io->items->count() OR $io->total < 0)
|
||||
if ($io->total < 0) {
|
||||
$this->warn(sprintf(' - Invoice totals [%3.2f] - skipping',$io->total));
|
||||
continue;
|
||||
}
|
||||
|
||||
$io->account_id = $o->id;
|
||||
|
||||
if ($this->option('list')) {
|
||||
$this->warn(sprintf('|%4s|%4s|%-50s|%8s|',
|
||||
$this->line(sprintf('|%4s|%4s|%-50s|%8s|',
|
||||
'SID',
|
||||
'PID',
|
||||
'Name',
|
||||
'Amount',
|
||||
));
|
||||
|
||||
foreach ($io->items as $oo) {
|
||||
foreach ($io->items_active as $oo) {
|
||||
$this->info(sprintf('|%4s|%4s|%-50s|%8.2f|',
|
||||
$oo->service_id,
|
||||
$oo->product_id,
|
||||
@ -70,8 +88,9 @@ class InvoiceGenerate extends Command
|
||||
}
|
||||
}
|
||||
|
||||
//dump($io);
|
||||
if ($this->option('preview')) {
|
||||
$this->info(sprintf('Invoice for Account [%d] - [%d] items totalling [%3.2f]',$o->id,$io->items->count(),$io->total));
|
||||
$this->info(sprintf('=> Invoice for Account [%d] - [%d] items totalling [%3.2f]',$o->id,$io->items_active->count(),$io->total));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -81,5 +100,7 @@ class InvoiceGenerate extends Command
|
||||
|
||||
$io->pushNew();
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
@ -3,14 +3,10 @@
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Mail\SocialLink;
|
||||
use App\Models\{ProviderOauth,ProviderToken,User,UserOauth};
|
||||
|
||||
class SocialLoginController extends Controller
|
||||
@ -105,46 +101,4 @@ class SocialLoginController extends Controller
|
||||
->intended('/home')
|
||||
->with('success','Token refreshed.');
|
||||
}
|
||||
|
||||
/**
|
||||
* We have identified the user and oauth, just need them to confirm the link
|
||||
*
|
||||
* @param $provider
|
||||
* @param UserOauth $ao
|
||||
* @param User $uo
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function link($provider,UserOauth $ao,User $uo): \Illuminate\View\View
|
||||
{
|
||||
// @note If this is sent now (send()), it results in the caller to be executed a second time (handleProviderCallback()).
|
||||
Mail::to($uo->email)->queue(new SocialLink($ao));
|
||||
|
||||
return view('auth.social_link')
|
||||
->with('oauthid',$ao->id)
|
||||
->with('provider',$provider);
|
||||
}
|
||||
|
||||
public function linkcomplete(Request $request,$provider)
|
||||
{
|
||||
// Load our oauth id
|
||||
$aoo = UserOauth::findOrFail($request->post('oauthid'));
|
||||
|
||||
// Check our email matches
|
||||
if (Arr::get($aoo->oauth_data,'email','invalid') !== $request->post('email'))
|
||||
return redirect('/login')->with('error','Account details didnt match to make link.');
|
||||
|
||||
// Check our token matches
|
||||
if ($aoo->link_token !== $request->post('token'))
|
||||
return redirect('/login')->with('error','Token details didnt match to make link.');
|
||||
|
||||
// Load our email.
|
||||
$uo = User::where('email',$request->post('email'))->firstOrFail();
|
||||
|
||||
$aoo->user_id = $uo->id;
|
||||
$aoo->save();
|
||||
Auth::login($uo);
|
||||
|
||||
return redirect()
|
||||
->intended('/home');
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
@ -18,7 +17,7 @@ use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\View\View;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
use App\Http\Requests\{ChargeAdd,ServiceChangeRequest};
|
||||
use App\Http\Requests\ServiceChangeRequest;
|
||||
use App\Mail\{CancelRequest,ChangeRequest};
|
||||
use App\Models\{Charge,Invoice,Product,Service};
|
||||
|
||||
@ -274,7 +273,7 @@ class ServiceController extends Controller
|
||||
*/
|
||||
public function domain_list(): View
|
||||
{
|
||||
$o = Service\Domain::serviceActive()
|
||||
$o = Service\Domain::ServiceActive()
|
||||
->serviceUserAuthorised(Auth::user())
|
||||
->select('service_domain.*')
|
||||
->join('services',['services.id'=>'service_domain.service_id'])
|
||||
@ -287,8 +286,7 @@ class ServiceController extends Controller
|
||||
|
||||
public function email_list(): View
|
||||
{
|
||||
// @todo Need to add the with path when calculating next_billed and price
|
||||
$o = Service\Email::serviceActive()
|
||||
$o = Service\Email::ServiceActive()
|
||||
->serviceUserAuthorised(Auth::user())
|
||||
->select('service_email.*')
|
||||
->join('services',['services.id'=>'service_email.service_id'])
|
||||
@ -314,15 +312,14 @@ class ServiceController extends Controller
|
||||
|
||||
public function hosting_list(): View
|
||||
{
|
||||
// @todo Need to add the with path when calculating next_billed and price
|
||||
$o = Service\Host::serviceActive()
|
||||
$o = Service\Host::ServiceActive()
|
||||
->serviceUserAuthorised(Auth::user())
|
||||
->select('service_host.*')
|
||||
->join('services',['services.id'=>'service_host.service_id'])
|
||||
->with(['service.account','service.product.type.supplied.supplier_detail.supplier','tld'])
|
||||
->get();
|
||||
|
||||
return view('theme.backend.adminlte.service.host.list')
|
||||
return view('theme.backend.adminlte.service.hosting.list')
|
||||
->with('o',$o);
|
||||
}
|
||||
|
||||
@ -471,7 +468,7 @@ class ServiceController extends Controller
|
||||
$o->type->save();
|
||||
|
||||
if ($validated->has('invoice_next_at'))
|
||||
$o->invoice_next_at = $validated->get('invoice_next_at');
|
||||
$o->invoice_next_at = $validated?->get('invoice_next_at');
|
||||
|
||||
if ($validated->has('recur_schedule'))
|
||||
$o->recur_schedule = $validated->get('recur_schedule');
|
||||
|
@ -52,7 +52,7 @@ class CancelRequest extends Mailable
|
||||
}
|
||||
|
||||
return $this
|
||||
->markdown('email.admin.service.cancel')
|
||||
->markdown('mail.admin.service.cancel')
|
||||
->subject($subject)
|
||||
->with(['site'=>$this->service->site]);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class ChangeRequest extends Mailable
|
||||
}
|
||||
|
||||
return $this
|
||||
->markdown('email.admin.service.change')
|
||||
->markdown('mail.admin.service.change')
|
||||
->subject($subject)
|
||||
->with(['site'=>$this->service->site]);
|
||||
}
|
||||
|
@ -2,21 +2,20 @@
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\Site;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
use App\Models\Invoice;
|
||||
|
||||
class InvoiceEmail extends Mailable
|
||||
class InvoiceEmail extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public $invoice;
|
||||
public $site;
|
||||
protected Invoice $io;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
@ -25,28 +24,33 @@ class InvoiceEmail extends Mailable
|
||||
*/
|
||||
public function __construct(Invoice $o)
|
||||
{
|
||||
$this->invoice = $o;
|
||||
$this->io = $o;
|
||||
$this->queue = 'user';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function build()
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
Config::set('site',Site::findOrFail($this->invoice->site_id));
|
||||
$this->site = config('site');
|
||||
return new Envelope(
|
||||
subject: sprintf('Invoice %d for services, due %s',
|
||||
$this->io->lid,
|
||||
$this->io->due_at->format('Y-m-d')),
|
||||
);
|
||||
}
|
||||
|
||||
return $this
|
||||
->markdown('email.user.invoice',['site'=>config('site')])
|
||||
->subject(sprintf( 'Invoice: %s - Total: $%s - Due: %s',
|
||||
$this->invoice->id,
|
||||
number_format($this->invoice->total,2),
|
||||
$this->invoice->due_at->format('Y-m-d')))
|
||||
->with([
|
||||
'user'=>$this->invoice->account->user,
|
||||
'site'=>$this->invoice->account->user->site,
|
||||
]);
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(
|
||||
markdown: 'mail.invoice',
|
||||
with: [
|
||||
'io'=>$this->io,
|
||||
'site'=>$this->io->site,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
57
app/Mail/InvoiceGeneratedAdmin.php
Normal file
57
app/Mail/InvoiceGeneratedAdmin.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
use App\Models\Invoice;
|
||||
|
||||
class InvoiceGeneratedAdmin extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
protected Invoice $io;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param Invoice $o
|
||||
*/
|
||||
public function __construct(Invoice $o)
|
||||
{
|
||||
$this->io = $o;
|
||||
$this->queue = 'admin';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
subject: sprintf('Invoice %d generated for %s, due %s',
|
||||
$this->io->lid,
|
||||
$this->io->account->name,
|
||||
$this->io->due_at->format('Y-m-d')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(
|
||||
markdown: 'mail.admin.invoice.generated',
|
||||
with: [
|
||||
'io'=>$this->io,
|
||||
'site'=>$this->io->site,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
@ -52,7 +52,7 @@ class OrderRequest extends Mailable
|
||||
}
|
||||
|
||||
return $this
|
||||
->markdown('email.admin.order.approve')
|
||||
->markdown('mail.admin.order.approve')
|
||||
->subject($subject)
|
||||
->with(['site'=>$this->service->site]);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class OrderRequestApprove extends Mailable
|
||||
}
|
||||
|
||||
return $this
|
||||
->markdown('email.admin.order.approve')
|
||||
->markdown('mail.admin.order.approve')
|
||||
->subject($subject)
|
||||
->with(['site'=>$this->so->site]);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ class OrderRequestReject extends Mailable
|
||||
Config::set('site',$this->service->site);
|
||||
|
||||
return $this
|
||||
->markdown('email.admin.order.reject')
|
||||
->markdown('mail.admin.order.reject')
|
||||
->subject(sprintf('Your order: #%s was rejected',$this->service->id))
|
||||
->with(['site'=>$this->service->site]);
|
||||
}
|
||||
|
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
use App\Models\{Site,User,UserOauth};
|
||||
|
||||
class SocialLink extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public string $token;
|
||||
public Site $site;
|
||||
public ?User $user;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param UserOauth $o
|
||||
*/
|
||||
public function __construct(UserOauth $o)
|
||||
{
|
||||
$this->site = $o->site;
|
||||
$this->token = $o->link_token;
|
||||
$this->user = $o->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
Config::set('site',$this->site);
|
||||
|
||||
return $this
|
||||
->markdown('email.system.social_link')
|
||||
->subject('Link your Account')
|
||||
->with([
|
||||
'site'=>$this->site,
|
||||
]);
|
||||
}
|
||||
}
|
@ -3,14 +3,12 @@
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
class TestEmail extends Mailable
|
||||
class Test extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
@ -33,10 +31,8 @@ class TestEmail extends Mailable
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
Config::set('site',$this->user->site);
|
||||
|
||||
return $this
|
||||
->markdown('email.system.test_email')
|
||||
->markdown('mail.test')
|
||||
->subject('Just a test...')
|
||||
->with([
|
||||
'site'=>$this->user->site,
|
@ -4,7 +4,6 @@ namespace App\Mail;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
@ -36,10 +35,10 @@ class TrafficMismatch extends Mailable
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
Config::set('site',$x=Site::find(1)); // @todo To auto determine;
|
||||
Config::set('site',$x=Site::where('url',config('app.url'))->sole());
|
||||
|
||||
return $this
|
||||
->markdown('email.system.broadband_traffic_mismatch')
|
||||
->markdown('mail.admin.service.traffic_mismatch')
|
||||
->subject('Traffic Mismatch for '.$this->date)
|
||||
->with([
|
||||
'site'=>$x,
|
||||
|
@ -253,13 +253,15 @@ class Account extends Model implements IDs
|
||||
|
||||
/* METHODS */
|
||||
|
||||
public function invoice_next(): Collection
|
||||
public function invoice_next(Carbon $date=NULL): Collection
|
||||
{
|
||||
// Collect all the invoice items for our active services
|
||||
$nextdate = ($x=$this
|
||||
$svs = $this
|
||||
->services_active
|
||||
->filter(fn($item)=>$item->isBilled() && $item->invoice_next)
|
||||
->sortBy(fn($item)=>(string)$item->invoice_next))
|
||||
->sortBy(fn($item)=>(string)$item->invoice_next);
|
||||
|
||||
// Collect all the invoice items for our active services
|
||||
$nextdate = $date ?: $svs
|
||||
->first()
|
||||
?->invoice_next
|
||||
->clone();
|
||||
@ -271,7 +273,7 @@ class Account extends Model implements IDs
|
||||
->subDay()
|
||||
->endOfday();
|
||||
|
||||
$items = $x
|
||||
$items = $svs
|
||||
->filter(fn($item)=>$item->invoice_next->lessThan($nextitemsdate))
|
||||
->sortBy(fn($item)=>$item->invoice_next.$item->name)
|
||||
->map(fn($item)=>$item->next_invoice_items($nextitemsdate))
|
||||
|
@ -75,7 +75,7 @@ class Charge extends Model
|
||||
return sprintf('%s %s',
|
||||
$this->description,
|
||||
$this->getAttribute('attributes')
|
||||
? join('|',unserialize($this->getAttribute('attributes')))
|
||||
? $this->getAttribute('attributes')->join('|')
|
||||
: '');
|
||||
}
|
||||
|
||||
|
@ -8,12 +8,14 @@ use Clarkeash\Doorman\Models\Invite;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Leenooks\Casts\LeenooksCarbon;
|
||||
use Leenooks\Traits\ScopeActive;
|
||||
|
||||
use App\Casts\CollectionOrNull;
|
||||
use App\Interfaces\IDs;
|
||||
use App\Traits\PushNew;
|
||||
use App\Mail\{InvoiceEmail,InvoiceGeneratedAdmin};
|
||||
use App\Traits\{PushNew,SiteID};
|
||||
|
||||
/**
|
||||
* Class Invoice
|
||||
@ -36,7 +38,7 @@ use App\Traits\PushNew;
|
||||
*/
|
||||
class Invoice extends Model implements IDs
|
||||
{
|
||||
use PushNew,ScopeActive;
|
||||
use PushNew,ScopeActive,SiteID;
|
||||
|
||||
protected $casts = [
|
||||
'created_at' => 'datetime:Y-m-d',
|
||||
@ -95,8 +97,8 @@ class Invoice extends Model implements IDs
|
||||
],
|
||||
];
|
||||
|
||||
// Array of items that can be updated with PushNew
|
||||
protected $pushable = ['items'];
|
||||
// Our related items that need to be updated when we call pushNew()
|
||||
protected $pushable = ['items_active'];
|
||||
|
||||
protected $with = [
|
||||
'items_active:id,start_at,stop_at,quantity,price_base,discount_amt,item_type,product_id,service_id,invoice_id',
|
||||
@ -108,6 +110,21 @@ class Invoice extends Model implements IDs
|
||||
|
||||
/* STATIC METHODS */
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::created(function($model) {
|
||||
// Send an email to an admin that the invoice was created
|
||||
$uo = User::where('email',config('osb.admin'))->sole();
|
||||
|
||||
Mail::to($uo->email)
|
||||
->send(new InvoiceGeneratedAdmin($model));
|
||||
|
||||
// @todo Queue an email to the user
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This works out what multiplier to use to change billing periods
|
||||
*
|
||||
@ -565,6 +582,28 @@ class Invoice extends Model implements IDs
|
||||
return parent::save($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the invoice being sent
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function send(): int
|
||||
{
|
||||
$result = Mail::to($this->account->user->email)
|
||||
->send(new InvoiceEmail($this));
|
||||
|
||||
$this->print_status = TRUE;
|
||||
|
||||
if ($this->reminders->has('sent'))
|
||||
$this->reminders->put('sent',collect($this->reminders->get('sent')));
|
||||
else
|
||||
$this->reminders->put('sent',collect());
|
||||
|
||||
$this->reminders->get('sent')->push(Carbon::now());
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group the invoice items by product ID, returning the number of products and total
|
||||
*
|
||||
@ -574,12 +613,20 @@ class Invoice extends Model implements IDs
|
||||
{
|
||||
$return = collect();
|
||||
|
||||
foreach ($this->items_active->groupBy('product_id') as $o) {
|
||||
$po = $o->first()->product;
|
||||
foreach ($this->items_active->groupBy('product_id') as $id => $o) {
|
||||
if (! $id) {
|
||||
$po = new Product;
|
||||
$po->translate = new ProductTranslate;
|
||||
$po->translate->name_detail = 'Miscellanious';
|
||||
|
||||
} else {
|
||||
$po = $o->first()->product;
|
||||
}
|
||||
|
||||
$po->count = count($o->pluck('service_id')->unique());
|
||||
|
||||
$return->push([
|
||||
'product' => $o->first()->product,
|
||||
'product' => $po,
|
||||
'services' => $o->pluck('service_id')->unique(),
|
||||
'sub_total' => $o->sum('sub_total'),
|
||||
'tax_total' => $o->sum('tax'),
|
||||
@ -589,4 +636,21 @@ class Invoice extends Model implements IDs
|
||||
|
||||
return $return->sortBy('product.name');
|
||||
}
|
||||
|
||||
public function summary_other(): Collection
|
||||
{
|
||||
$result = collect();
|
||||
|
||||
foreach ($this->items_active->whereNull('service_id') as $o) {
|
||||
dd($o);
|
||||
$result->push([
|
||||
'description' => 'Account Items',
|
||||
'sub_total' => $o->sub_total,
|
||||
'tax_total' => $o->tax,
|
||||
'total' => $o->total,
|
||||
]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -52,6 +52,22 @@ class InvoiceItem extends Model
|
||||
127 => 'Rounding', // * SERVICE_ID is NULL, MODULE_ID is NULL, MODULE_REF is NULL
|
||||
];
|
||||
|
||||
/* STATIC */
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::created(function($model) {
|
||||
// If this items were a charge, we'll update the charge to processed
|
||||
if (($model->module_id === 30) && $model->module_ref) {
|
||||
$o = Charge::findOrfail($model->module_ref);
|
||||
$o->processed = TRUE;
|
||||
$o->save();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* RELATIONS */
|
||||
|
||||
public function invoice()
|
||||
|
@ -64,12 +64,14 @@ abstract class Type extends Model implements ServiceItem
|
||||
|
||||
public function hasExpired(): bool
|
||||
{
|
||||
return (! $this->inContract()) && ($this->service->invoice_next_at && $this->service->invoice_next_at->isPast());
|
||||
return (! $this->inContract())
|
||||
&& ($this->service->invoice_next && $this->service->invoice_next->isPast());
|
||||
}
|
||||
|
||||
public function inContract(): bool
|
||||
{
|
||||
return $this->expire_at && $this->expire_at->isFuture();
|
||||
return $this->expire_at
|
||||
&& $this->expire_at->isFuture();
|
||||
}
|
||||
|
||||
/* ATTRIBUTES */
|
||||
|
@ -72,7 +72,8 @@ class User extends Authenticatable implements IDs
|
||||
*/
|
||||
public function sendPasswordResetNotification($token)
|
||||
{
|
||||
$this->notify((new ResetPasswordNotification($token))->onQueue('high'));
|
||||
$this->notify((new ResetPasswordNotification($token))
|
||||
->onQueue('user'));
|
||||
}
|
||||
|
||||
/* INTERFACES */
|
||||
|
@ -25,7 +25,7 @@ class ResetPassword extends ResetPasswordNotification implements ShouldQueue
|
||||
}
|
||||
|
||||
return (new MailMessage)
|
||||
->markdown('email.user.passwordreset',[
|
||||
->markdown('mail.password.reset',[
|
||||
'site'=>$notifiable->site,
|
||||
'user'=>$notifiable,
|
||||
'reset_link'=>route('password.reset',$this->token,true),
|
||||
|
@ -8,6 +8,7 @@
|
||||
namespace App\Traits;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
trait PushNew
|
||||
{
|
||||
@ -22,7 +23,7 @@ trait PushNew
|
||||
// us to recurse into all of these nested relations for the model instance.
|
||||
foreach ($this->relations as $key => $models) {
|
||||
// If we are not pushable, jump to the next item.
|
||||
if (! is_array($this->pushable) OR ! in_array($key,$this->pushable))
|
||||
if ((! is_array($this->pushable)) || (! in_array($key,$this->pushable)))
|
||||
continue;
|
||||
|
||||
$models = $models instanceof Collection
|
||||
@ -32,6 +33,8 @@ trait PushNew
|
||||
$model->setAttribute($this->getForeignKey(),$this->{$this->getKeyName()});
|
||||
|
||||
if (! $model->pushNew()) {
|
||||
Log::alert('Failed to save model',['attrs'=>$model->getAttributes()]);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
6
composer.lock
generated
6
composer.lock
generated
@ -3056,11 +3056,11 @@
|
||||
},
|
||||
{
|
||||
"name": "leenooks/laravel",
|
||||
"version": "11.1.8",
|
||||
"version": "11.1.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://gitea.dege.au/laravel/leenooks.git",
|
||||
"reference": "8acc3a91af7e4ce622aec60934a2f942b4a19eda"
|
||||
"reference": "293d9913c65143f00e3051bff32d15c97644bd15"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@ -3093,7 +3093,7 @@
|
||||
"laravel",
|
||||
"leenooks"
|
||||
],
|
||||
"time": "2024-07-31T12:40:35+00:00"
|
||||
"time": "2024-08-01T07:32:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "leenooks/passkey",
|
||||
|
@ -4,5 +4,6 @@ return [
|
||||
'language_id' => 1,
|
||||
'invoice_text' => 'Thank you for using our Internet Services.',
|
||||
'invoice_days' => 30, // Days in Advance to invoice
|
||||
'invoice_review' => 3, // Days to review an invoice before it is emailed
|
||||
'admin' => env('APP_ADMIN'),
|
||||
];
|
30
resources/views/components/form/domain.blade.php
Normal file
30
resources/views/components/form/domain.blade.php
Normal file
@ -0,0 +1,30 @@
|
||||
@use(App\Models\TLD)
|
||||
|
||||
<div class="form-group has-validation">
|
||||
@if(isset($label))
|
||||
<label for="domain_name">{{ $label }}</label>
|
||||
@endif
|
||||
<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($name.'.domain_name')is-invalid @enderror" id="domain_name" name="{{ $name }}[domain_name]" placeholder="Domain Name..." value="{{ old($name.'.domain_name',$nameValue ?? '') }}" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">.</span>
|
||||
</div>
|
||||
<select class="form-control col-3" name="{{ $name }}[tld_id]">
|
||||
@foreach(TLD::orderBy('name')->get() as $oo)
|
||||
<option value="{{ $oo->id }}" @selected($oo->id == old($name.'.tld_id',$tldValue ?? ''))>{{ $oo->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error($name.'.domain_name')
|
||||
{{ $message }}
|
||||
@else
|
||||
Domain Name is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Domain Name</span>
|
||||
</div>
|
@ -1,21 +0,0 @@
|
||||
@component('mail::message',['site'=>$site,'heading'=>'Link Your Account'])
|
||||
Hi {{ isset($user) ? $user->name_full.',' : '' }}
|
||||
|
||||
A request was made to link your account to a social login.
|
||||
If you didnt make this request, you can ignore this, and the request will be ignored.
|
||||
If you did make the request, then please enter the code displayed below.
|
||||
|
||||
@component('mail::panel')
|
||||
{{ $token }}
|
||||
@endcomponent
|
||||
|
||||
Once you've keyed in this code, you'll be able to login to your account using your social login instead of a username and a password.
|
||||
|
||||
Thanks,
|
||||
|
||||
{{ config('mail.from.name') }}
|
||||
|
||||
@component('mail::subcopy')
|
||||
If you didnt make this request, you can safely ignore this email - no change was made to your account, nor was it accessed by an unauthorised person.
|
||||
@endcomponent
|
||||
@endcomponent
|
@ -1,27 +0,0 @@
|
||||
@component('mail::message',['site'=>$site,'heading'=>'Invoice: '.$invoice->id])
|
||||
Hi {{ isset($user) ? $user->name_full.',' : '' }}
|
||||
|
||||
A new invoice has been generated on your account. A summary of that invoice is below.
|
||||
|
||||
@component('mail::table')
|
||||
| # | ID | Name | Amount |
|
||||
| -: | - |:-----| ------:|
|
||||
@foreach ($invoice->summary_products() as $item)
|
||||
| {{ $item['services']->count() }} | {{ $item['product']->lid }} | {{ $item['product']->name }} | ${{ number_format($item['total'],2) }} |
|
||||
@endforeach
|
||||
||| Sub Total | ${{ number_format($invoice->sub_total,2) }} |
|
||||
||| Tax | ${{ number_format($invoice->tax_total,2) }} |
|
||||
||| Total | ${{ number_format($invoice->total,2) }} |
|
||||
||| Payments | ${{ number_format($invoice->paid,2) }} |
|
||||
||| Still Due | ${{ number_format($invoice->due,2) }} |
|
||||
@endcomponent
|
||||
|
||||
If you would like a PDF copy of that invoice, please click on the link below:
|
||||
|
||||
@component('mail::panel',['url'=>$invoice->download_link()])
|
||||
Download PDF
|
||||
@endcomponent
|
||||
|
||||
Thanks,<br>
|
||||
{{ config('mail.from.name') }}
|
||||
@endcomponent
|
25
resources/views/mail/admin/invoice/generated.blade.php
Normal file
25
resources/views/mail/admin/invoice/generated.blade.php
Normal file
@ -0,0 +1,25 @@
|
||||
@component('mail::message',['site'=>$site,'heading'=>'Invoice: #'.$io->id,'subheading'=>sprintf('Due: <strong>%s</strong>',$io->due_at->format('Y-m-d'))])
|
||||
Hi {{ isset($user) ? $user->name_full.',' : '' }}
|
||||
|
||||
A new invoice has been generated for <strong>{{ $io->account->name }}</strong>. A summary of that invoice is below:
|
||||
|
||||
@component('mail::table')
|
||||
| ID | # | Name | Amount |
|
||||
| -: | -: |:-----| ------:|
|
||||
@foreach ($io->summary_products() as $item)
|
||||
| {{ $item['product']->lid }} | {{ $item['services']->count() }} | {{ $item['product']->name }} | ${{ number_format($item['total'],2) }} |
|
||||
@endforeach
|
||||
||| Sub Total | ${{ number_format($io->sub_total,2) }} |
|
||||
||| Tax | ${{ number_format($io->tax_total,2) }} |
|
||||
||| **Total** | **${{ number_format($io->total,2) }}** |
|
||||
@endcomponent
|
||||
|
||||
This invoice will be automatically emailed in {{ config('osb.invoice_review') }} days time.
|
||||
|
||||
@component('mail::button',['url'=>url('u/invoice',$io->id)])
|
||||
Review
|
||||
@endcomponent
|
||||
|
||||
Thanks,<br>
|
||||
{{ config('mail.from.name') }}
|
||||
@endcomponent
|
@ -1,8 +1,6 @@
|
||||
@component('mail::message',['site'=>$site])
|
||||
# Your order was rejected.
|
||||
|
||||
@component('mail::panel')
|
||||
|
||||
@component('mail::table')
|
||||
| Service | Details |
|
||||
| :---------- | :---------------- |
|
||||
@ -22,8 +20,6 @@
|
||||
|
||||
**REASON:** {{ $reason }}
|
||||
|
||||
@endcomponent
|
||||
|
||||
Thanks,<br>
|
||||
{{ config('app.name') }}
|
||||
@endcomponent
|
29
resources/views/mail/invoice.blade.php
Normal file
29
resources/views/mail/invoice.blade.php
Normal file
@ -0,0 +1,29 @@
|
||||
@component('mail::message',['site'=>$site,'heading'=>'Invoice: #'.$io->lid,'subheading'=>sprintf('Due: <strong>%s</strong>',$io->due_at->format('Y-m-d'))])
|
||||
Hi {{ isset($user) ? $user->name_full.',' : '' }}
|
||||
|
||||
A new invoice has been generated on your account. A summary of that invoice is below:
|
||||
|
||||
@component('mail::table')
|
||||
| ID | # | Name | Amount |
|
||||
| -: | -: |:-----| ------:|
|
||||
@foreach ($io->summary_products() as $item)
|
||||
| {{ $item['product']->lid }} | {{ $item['services']->count() }} | {{ $item['product']->name }} | ${{ number_format($item['total'],2) }} |
|
||||
@endforeach
|
||||
||| Sub Total | ${{ number_format($io->sub_total,2) }} |
|
||||
||| Tax | ${{ number_format($io->tax_total,2) }} |
|
||||
||| **Total** | **${{ number_format($io->total,2) }}** |
|
||||
@if($io->paid)
|
||||
||| Payments | ${{ number_format($io->paid,2) }} |
|
||||
||| Still Due | ${{ number_format($io->due,2) }} |
|
||||
@endif
|
||||
@endcomponent
|
||||
|
||||
If you would like a PDF copy of that invoice, please click on the link below:
|
||||
|
||||
@component('mail::button',['url'=>$io->download_link()])
|
||||
Download
|
||||
@endcomponent
|
||||
|
||||
Thanks,<br>
|
||||
{{ config('mail.from.name') }}
|
||||
@endcomponent
|
@ -1,17 +1,19 @@
|
||||
@component('mail::message',['site'=>$site,'heading'=>'Password Reset'])
|
||||
Hi {{ isset($user) ? $user->name_full.',' : '' }}
|
||||
|
||||
You are receiving this email because we received a password reset request for your account.
|
||||
|
||||
If you did not request a password reset, no further action is required.
|
||||
You are receiving this email because we received a password reset request for your account. If you did not request a password reset, no further action is required.
|
||||
|
||||
To reset your password, please follow this link, or click on the URL below:
|
||||
@component('mail::panel',['url'=>$reset_link])
|
||||
Reset Password
|
||||
@component('mail::button',['url'=>$reset_link])
|
||||
Reset Password
|
||||
@endcomponent
|
||||
|
||||
@component('mail::subcopy')
|
||||
Reset password: {{ $reset_link }}
|
||||
@component('mail::subcontent')
|
||||
If the button above doesnt work, you can copy and paste this link into your browser, and take it from there:
|
||||
|
||||
```
|
||||
{{ $reset_link }}
|
||||
```
|
||||
@endcomponent
|
||||
|
||||
Thanks,<br>
|
@ -1,37 +0,0 @@
|
||||
@if(($x=$list)->count())
|
||||
<div class="card card-light">
|
||||
<div class="card-header">
|
||||
<h1 class="card-title">Pending Charges</h1>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Date Created</th>
|
||||
<th>Date Charge</th>
|
||||
<th>Service</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach ($x as $co)
|
||||
<tr>
|
||||
<td><a href="{{ url('a/charge/addedit',[$co->id]) }}">{{ $co->id }}</a></td>
|
||||
<td>{{ $co->created_at->format('Y-m-d') }}</td>
|
||||
<td>{{ $co->charge_at ? $co->charge_at->format('Y-m-d') : '-' }}</td>
|
||||
<td>{{ $co->service->sid }}</td>
|
||||
<td>{{ $co->type }}</td>
|
||||
<td>{{ $co->description }}</td>
|
||||
<td class="text-right">{{ number_format($co->quantity*$co->amount,2) }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
@ -1,80 +0,0 @@
|
||||
@extends('adminlte::layouts.auth')
|
||||
|
||||
@section('htmlheader_title')
|
||||
Link Account
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="login-box">
|
||||
<div class="login-logo">
|
||||
<a>{!! config('app.name_html_long') !!}</a>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success">
|
||||
<strong>NOTE:</strong> Link your account.<br><br>
|
||||
<ul>
|
||||
<li>An email has been sent to you with a token, please use those details here:</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@if (count($errors) > 0)
|
||||
<div class="alert alert-danger">
|
||||
<strong>Whoops!</strong> {{ trans('adminlte_lang::message.someproblems') }}<br><br>
|
||||
<ul>
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- /.login-logo -->
|
||||
<div class="card">
|
||||
<div class="card-body login-card-body">
|
||||
<p class="login-box-msg">Link your account</p>
|
||||
|
||||
<form method="post" action="{{ url('/auth/'.$provider.'/linkcomplete') }}">
|
||||
{{ csrf_field() }}
|
||||
<input type="hidden" name="oauthid" value="{{ $oauthid }}">
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<input type="email" name="email" class="form-control" placeholder="Email">
|
||||
<div class="input-group-append">
|
||||
<span class="fa fa-envelope input-group-text"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<input type="password" name="token" class="form-control" placeholder="Token">
|
||||
<div class="input-group-append">
|
||||
<span class="fa fa-lock input-group-text"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-4">
|
||||
<button type="submit" name="submit" class="btn btn-primary btn-block btn-flat">Link</button>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="mb-1">
|
||||
<a name="reset" href="{{ url('/password/reset') }}">{{ trans('adminlte_lang::message.forgotpassword') }}</a>
|
||||
</p>
|
||||
|
||||
@isset($register)
|
||||
<p class="mb-0">
|
||||
<a href="register.html" class="text-center">Register a new account</a>
|
||||
</p>
|
||||
@endisset
|
||||
</div>
|
||||
<!-- /.login-card-body -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.login-box -->
|
||||
@endsection
|
@ -1,19 +0,0 @@
|
||||
<!-- Terms and conditions modal -->
|
||||
<div class="modal fade" id="termsModal" tabindex="-1" role="dialog" aria-labelledby="Terms and conditions" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Terms and conditions</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<p>Lorem ipsum dolor sit amet, veniam numquam has te. No suas nonumes recusabo mea, est ut graeci definitiones. His ne melius vituperata scriptorem, cum paulo copiosae conclusionemque at. Facer inermis ius in, ad brute nominati referrentur vis. Dicat erant sit ex. Phaedrum imperdiet scribentur vix no, ad latine similique forensibus vel.</p>
|
||||
<p>Dolore populo vivendum vis eu, mei quaestio liberavisse ex. Electram necessitatibus ut vel, quo at probatus oportere, molestie conclusionemque pri cu. Brute augue tincidunt vim id, ne munere fierent rationibus mei. Ut pro volutpat praesent qualisque, an iisque scripta intellegebat eam.</p>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,43 +0,0 @@
|
||||
<table class="table table-bordered w-100" id="invoices">
|
||||
<thead>
|
||||
<tr>
|
||||
<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 ($o->invoices as $io)
|
||||
<tr>
|
||||
<td class="text-right"><a href="{{ url('u/invoice',$io->id) }}">{{ $io->id }}</a></td>
|
||||
<td class="text-right">{{ $io->created_at->format('Y-m-d') }}</td>
|
||||
<td class="text-right">{{ $io->due_at->format('Y-m-d') }}</td>
|
||||
<td class="text-right">${{ number_format($io->total,2) }}</td>
|
||||
<td class="text-right">${{ number_format($io->paid,2) }}</td>
|
||||
<td class="text-right">${{ number_format($io->due,2) }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@section('page-scripts')
|
||||
@css(datatables,bootstrap4)
|
||||
@js(datatables,bootstrap4|responsive)
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#invoices').DataTable( {
|
||||
responsive: true,
|
||||
order: [1, 'desc']
|
||||
});
|
||||
|
||||
$('#invoices tbody').on('click','tr', function () {
|
||||
$(this).toggleClass('selected');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -128,6 +128,19 @@
|
||||
@endforeach
|
||||
@endforeach
|
||||
@endforeach
|
||||
|
||||
@if($o->summary_other()->count())
|
||||
<tr>
|
||||
<td colspan="7">{{ $item['description'] }}</td>
|
||||
</tr>
|
||||
@foreach($o->summary_other() as $item)
|
||||
<tr>
|
||||
<td colspan="2"> </td>
|
||||
|
||||
<td>{{ $item['description'] }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -46,7 +46,7 @@
|
||||
<td>{{ $oo->registrar->name }}</td>
|
||||
<td>{{ $oo->registrar_ns }}</td>
|
||||
<td>@if ($oo->service->isBilled()) {{ $oo->service->invoice_next->format('Y-m-d') }}@else - @endif</td>
|
||||
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items(TRUE)->sum('total'),2) }}@else - @endif</td>
|
||||
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items()->sum('total'),2) }}@else - @endif</td>
|
||||
<td>{{ $oo->service->billing_interval_string }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@ -58,15 +58,9 @@
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('page-scripts')
|
||||
@css(datatables,bootstrap4|rowgroup)
|
||||
@js(datatables,bootstrap4|rowgroup)
|
||||
@pa(datatables,rowgroup)
|
||||
|
||||
<style>
|
||||
.strike {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
</style>
|
||||
@section('page-scripts')
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#services').DataTable({
|
||||
@ -81,10 +75,6 @@
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
$('tbody').on('click','tr', function () {
|
||||
$(this).toggleClass('selected');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -50,7 +50,7 @@
|
||||
<td>@if($oo->admin_user){{ $oo->admin_user }}/{{ $oo->admin_pass }}@else @endif</td>
|
||||
<td class="text-right">{{ number_format($oo->accounts ?: 0) }}</td>
|
||||
<td>@if ($oo->service->isBilled()) {{ $oo->service->invoice_next->format('Y-m-d') }} @else - @endif</td>
|
||||
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items(TRUE)->sum('total'),2) }}@else - @endif</td>
|
||||
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items()->sum('total'),2) }}@else - @endif</td>
|
||||
<td>{{ $oo->service->billing_interval_string }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@ -62,15 +62,9 @@
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('page-scripts')
|
||||
@css(datatables,bootstrap4|rowgroup)
|
||||
@js(datatables,bootstrap4|rowgroup)
|
||||
@pa(datatables,rowgroup)
|
||||
|
||||
<style>
|
||||
.strike {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
</style>
|
||||
@section('page-scripts')
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#services').DataTable({
|
||||
@ -85,10 +79,6 @@
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
$('tbody').on('click','tr', function () {
|
||||
$(this).toggleClass('selected');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -44,7 +44,7 @@
|
||||
<td>{{ $oo->service_expire ? $oo->service_expire->format('Y-m-d') : '-' }}</td>
|
||||
<td>{{ $oo->service->product->supplier->name }}</td>
|
||||
<td>@if ($oo->service->isBilled()) {{ $oo->service->invoice_next->format('Y-m-d') }}@else - @endif</td>
|
||||
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items(TRUE)->sum('total'),2) }}@else - @endif</td>
|
||||
<td>@if (! $oo->service->external_billing)${{ number_format($oo->service->next_invoice_items()->sum('total'),2) }}@else - @endif</td>
|
||||
<td>{{ $oo->service->billing_interval_string }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@ -56,15 +56,9 @@
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('page-scripts')
|
||||
@css(datatables,bootstrap4|rowgroup)
|
||||
@js(datatables,bootstrap4|rowgroup)
|
||||
@pa(datatables,rowgroup)
|
||||
|
||||
<style>
|
||||
.strike {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
</style>
|
||||
@section('page-scripts')
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#services').DataTable({
|
||||
@ -79,10 +73,6 @@
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
$('tbody').on('click','tr', function () {
|
||||
$(this).toggleClass('selected');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -72,10 +72,6 @@
|
||||
},
|
||||
orderFixed: [1, 'asc']
|
||||
});
|
||||
|
||||
$('#service_movements tbody').on('click','tr', function () {
|
||||
$(this).toggleClass('selected');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -26,6 +26,7 @@
|
||||
<strong>NOTE</strong>: A plan setup fee is normally not applicable to Broadband changes, but a plan change fee normally is.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section('page-scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
@ -35,7 +35,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||
<x-leenooks::form.date id="expire_at" name="broadband[expire_at]" icon="fa-calendar" label="Contract End" old="broadband.expire_at" :value="$o->expire_at?->format('Y-m-d') ?: ($o->connect_at?->addMonths($o->contract_term)->format('Y-m-d'))"/>
|
||||
<x-leenooks::form.date id="expire_at" name="broadband[expire_at]" icon="fa-calendar" label="Contract End" old="broadband.expire_at" :value="($o->expire_at ?: $o->connect_at?->addMonths($o->contract_term))?->format('Y-m-d')"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -1,44 +1,15 @@
|
||||
@use(App\Models\Domain)
|
||||
@use(App\Models\DomainRegistrar)
|
||||
@use(App\Models\Service\Domain,ServiceDomain)
|
||||
|
||||
<!-- o=Service\Domain::class -->
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-9 col-md-12 col-xl-7">
|
||||
<div class="form-group">
|
||||
<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" style="width:55%;" class="form-control text-right @error('domain_name') is-invalid @enderror" id="domain_name" name="domain[domain_name]" placeholder="Domain Name..." value="{{ old('domain.domain_name',$o->domain_name) }}" required>
|
||||
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">.</span>
|
||||
</div>
|
||||
|
||||
<select style="width:25%;" class="form-control @error('tld_id') is-invalid @enderror" id="tld_id" name="domain[tld_id]">
|
||||
@foreach(\App\Models\TLD::orderBy('name')->get() as $oo)
|
||||
<option value="{{ $oo->id }}" @if($oo->id == old('domain.tld_id',$o->tld_id))selected @endif>{{ $oo->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('domain_name')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
@error('tld_id')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<x-form.domain name="domain" label="Domain Name" :name_value="$o->domain_name" :tld_value="$o->tld_id"/>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||
@include('adminlte::widget.form_date',[
|
||||
'label'=>'Expiry',
|
||||
'icon'=>'fas fa-calendar',
|
||||
'id'=>'expire_at',
|
||||
'old'=>'domain.expire_at',
|
||||
'name'=>'domain[expire_at]',
|
||||
'value'=>$o->expire_at ? $o->expire_at->format('Y-m-d') : ($o->connect_at ? $o->connect_at->addMonths($o->contract_term)->format('Y-m-d') : ''),
|
||||
])
|
||||
<x-leenooks::form.date id="expire_at" name="domain[expire_at]" icon="fa-calendar" label="Expiry" old="domain.expire_at" :value="$o->expire_at?->format('Y-m-d')"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -47,77 +18,27 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||
@include('adminlte::widget.form_select',[
|
||||
'label'=>'Registrar',
|
||||
'icon'=>'fas fa-handshake',
|
||||
'id'=>'domain_registrar_id',
|
||||
'old'=>'domain.domain_registrar_id',
|
||||
'name'=>'domain[domain_registrar_id]',
|
||||
'options'=>\App\Models\DomainRegistrar::active()->orderBy('name')->get()->transform(function($item) { return ['id'=>$item->id,'value'=>$item->name]; }),
|
||||
'value'=>$o->domain_registrar_id ?? '',
|
||||
])
|
||||
<x-leenooks::form.select id="domain_registrar_id" name="domain[domain_registrar_id]" icon="fa-handshake" label="Registrar" :value="$o->domain_registrar_id" :options="DomainRegistrar::active()->orderBy('name')->get()->transform(fn($item)=>['id'=>$item->id,'value'=>$item->name])"/>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-9 col-md-12 col-xl-6">
|
||||
@include('adminlte::widget.form_text',[
|
||||
'label'=>'Registrar Account',
|
||||
'icon'=>'fas fa-user-circle',
|
||||
'id'=>'registrar_account',
|
||||
'old'=>'domain.registrar_account',
|
||||
'name'=>'domain[registrar_account]',
|
||||
'value'=>$o->registrar_account ?? '',
|
||||
])
|
||||
<x-leenooks::form.text id="registrar_account" name="domain[registrar_account]" icon="fa-user-circle" label="Registrar Username" :value="$o->registrar_account"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||
@include('adminlte::widget.form_select',[
|
||||
'label'=>'DNS Location',
|
||||
'icon'=>'fas fa-project-diagram',
|
||||
'id'=>'registrar_ns',
|
||||
'old'=>'domain.registrar_ns',
|
||||
'name'=>'domain[registrar_ns]',
|
||||
'options'=>\App\Models\Service\Domain::select('registrar_ns')->distinct()->orderBy('registrar_ns')->get()->transform(function($item) { return ['id'=>$item->registrar_ns,'value'=>$item->registrar_ns]; }),
|
||||
'value'=>$o->registrar_ns ?? '',
|
||||
'addvalues'=>TRUE,
|
||||
])
|
||||
<x-leenooks::form.select id="registrar_ns" name="domain[registrar_ns]" icon="fa-project-diagram" label="DNS Location" :value="$o->registrar_ns" :options="ServiceDomain::select('registrar_ns')->distinct()->orderBy('registrar_ns')->get()->transform(fn($item)=>['id'=>$item->registrar_ns,'value'=>$item->registrar_ns])"/>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-9 col-md-12 col-xl-6">
|
||||
@include('adminlte::widget.form_text',[
|
||||
'label'=>'Registrar Username',
|
||||
'icon'=>'fas fa-user',
|
||||
'id'=>'registrar_username',
|
||||
'old'=>'domain.registrar_username',
|
||||
'name'=>'domain[registrar_username]',
|
||||
'value'=>$o->registrar_username ?? '',
|
||||
])
|
||||
<x-leenooks::form.text id="registrar_username" name="domain[registrar_username]" icon="fa-user" label="Registrar Username" :value="$o->registrar_username"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<p class="h6">Service Dates</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||
@include('adminlte::widget.form_date',[
|
||||
'label'=>'Registered Date',
|
||||
'icon'=>'fas fa-calendar',
|
||||
'id'=>'start_at',
|
||||
'old'=>'start_at',
|
||||
'name'=>'start_at',
|
||||
'value'=>$o->service->start_at ? $o->service->start_at->format('Y-m-d') : '',
|
||||
])
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@pa(select2,autofocus)
|
||||
|
||||
@section('page-scripts')
|
||||
@css(select2)
|
||||
@js(select2,autofocus)
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#tld_id').select2({
|
||||
|
@ -1,156 +1,36 @@
|
||||
<!-- o = App\Models\Service\Email::class -->
|
||||
<!-- o=Service\Email::class -->
|
||||
<div class="row">
|
||||
<!-- DOMAIN NAME -->
|
||||
<div class="col-6">
|
||||
<div class="form-group has-validation">
|
||||
<label for="domain_name">Email 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('email.domain_name') is-invalid @enderror" id="domain_name" name="email[domain_name]" placeholder="Domain Name..." value="{{ old('email.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="email[tld_id]">
|
||||
@foreach(\App\Models\TLD::orderBy('name')->get() as $oo)
|
||||
<option value="{{ $oo->id }}" @if($oo->id == old('email.tld_id',$o->tld_id))selected @endif>{{ $oo->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('email.domain_name')
|
||||
{{ $message }}
|
||||
@else
|
||||
Domain Name is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Domain Name</span>
|
||||
</div>
|
||||
<div class="col-12 col-sm-9 col-md-12 col-xl-7">
|
||||
<x-form.domain name="email" label="Email Domain Name" :name_value="$o->domain_name" :tld_value="$o->tld_id"/>
|
||||
</div>
|
||||
|
||||
<!-- EXPIRY -->
|
||||
<div class="col-3">
|
||||
<div class="form-group has-validation">
|
||||
<label for="expire_at">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('email.expire_at') is-invalid @enderror" id="expire_at" name="email[expire_at]" value="{{ old('email.expire_at',($o->expire_at ? $o->expire_at->format('Y-m-d') : NULL)) }}">
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('email.expire_at')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Email Hosting Expires</span>
|
||||
</div>
|
||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||
<x-leenooks::form.date id="expire_at" name="email[expire_at]" icon="fa-calendar" label="Expiry" old="email.expire_at" :value="($o->expire_at ?: $o->connect_at?->addMonths($o->contract_term))?->format('Y-m-d')"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- ADMIN URL -->
|
||||
<div class="col-9">
|
||||
<div class="form-group has-validation">
|
||||
<label for="admin_url">Hosting Admin URL</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fab fa-fw fa-safari"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control @error('email.admin_url') is-invalid @enderror" id="admin_url" name="email[admin_url]" placeholder="Admin URL..." value="{{ old('email.admin_url',$o->admin_url) }}">
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('email.admin_url')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Admin URL</span>
|
||||
</div>
|
||||
<x-leenooks::form.text id="admin_url" name="email[admin_url]" icon="fa-user" label="Hosting Admin URL" placeholder="Admin URL..." old="email.admin_url" :value="$o->admin_url"/>
|
||||
</div>
|
||||
|
||||
<!-- ACCOUNTS -->
|
||||
<div class="col-3">
|
||||
<div class="form-group has-validation">
|
||||
<label for="accounts">Accounts</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-hashtag"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control @error('email.accounts') is-invalid @enderror" id="accounts" name="email[accounts]" placeholder="Accounts" value="{{ old('email.accounts',$o->accounts) }}">
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('email.accounts')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper"># Accounts</span>
|
||||
</div>
|
||||
<x-leenooks::form.text id="accounts" name="email[accounts]" icon="fa-user" label="Accounts" placeholder="Admin URL..." helper="# Accounts" old="email.accounts" :value="$o->accounts"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- ADMIN USER -->
|
||||
<div class="col-6">
|
||||
<div class="form-group has-validation">
|
||||
<label for="admin_user">Admin User</label>
|
||||
<div class="input-group flex-nowrap">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-user"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control @error('email.admin_user') is-invalid @enderror" id="admin_user" name="email[admin_user]" placeholder="Admin USER" value="{{ old('email.admin_user',$o->admin_user) }}">
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('email.admin_user')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Admin USER</span>
|
||||
</div>
|
||||
<x-leenooks::form.text id="admin_user" name="email[admin_user]" icon="fa-user" label="Admin Username" old="email.admin_user" :value="$o->admin_user"/>
|
||||
</div>
|
||||
|
||||
<!-- ADMIN PASS -->
|
||||
<div class="col-6">
|
||||
<div class="form-group has-validation">
|
||||
<label for="admin_pass">Admin Pass</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-lock"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control @error('email.admin_pass') is-invalid @enderror" id="admin_pass" name="email[admin_pass]" value="{{ old('email.admin_pass',$o->admin_pass) }}">
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('email.admin_pass')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Admin PASSWORD</span>
|
||||
</div>
|
||||
<x-leenooks::form.text id="admin_pass" name="email[admin_pass]" icon="fa-lock" label="Admin Password" :value="$o->admin_pass"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section('page-scripts')
|
||||
@css(select2)
|
||||
@js(select2,autofocus)
|
||||
|
||||
<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() {
|
||||
// @todo This is taking up too much width
|
||||
//$('#tld_id').select2();
|
||||
});
|
||||
</script>
|
||||
@append
|
||||
</div>
|
@ -1,98 +0,0 @@
|
||||
<!-- o = App\Models\Service\Host::class -->
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-9 col-md-12 col-xl-7">
|
||||
<div class="form-group">
|
||||
<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" style="width:55%;" class="form-control text-right @error('domain_name') is-invalid @enderror" id="domain_name" name="host[domain_name]" placeholder="Domain Name..." value="{{ old('host.domain_name',$o->domain_name) }}" required>
|
||||
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">.</span>
|
||||
</div>
|
||||
|
||||
<select style="width:25%;" class="form-control @error('tld_id') is-invalid @enderror" id="tld_id" name="host[tld_id]">
|
||||
@foreach(\App\Models\TLD::orderBy('name')->get() as $oo)
|
||||
<option value="{{ $oo->id }}" @if($oo->id == old('host.tld_id',$o->tld_id))selected @endif>{{ $oo->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('domain_name')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
@error('tld_id')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||
@include('adminlte::widget.form_date',[
|
||||
'label'=>'Expiry',
|
||||
'id'=>'expire_at',
|
||||
'old'=>'host.expire_at',
|
||||
'name'=>'host[expire_at]',
|
||||
'value'=>$o->expire_at ? $o->expire_at->format('Y-m-d') : ($o->connect_at ? $o->connect_at->addMonths($o->contract_term)->format('Y-m-d') : ''),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<p class="h6">Hosting Details</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||
@include('adminlte::widget.form_select',[
|
||||
'label'=>'Hosting Server',
|
||||
'icon'=>'fas fa-handshake',
|
||||
'id'=>'supplier_host_server_id',
|
||||
'old'=>'host.supplier_host_server_id',
|
||||
'name'=>'host[supplier_host_server_id]',
|
||||
'options'=>\App\Models\SupplierHostServer::active()->orderBy('name')->get()->transform(function($item) { return ['id'=>$item->id,'value'=>$item->name]; }),
|
||||
'value'=>$o->supplier_host_server_id ?? '',
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-9 col-md-12 col-xl-7">
|
||||
@include('adminlte::widget.form_text',[
|
||||
'label'=>'Admin User',
|
||||
'icon'=>'fas fa-user',
|
||||
'id'=>'host_username',
|
||||
'old'=>'host.host_username',
|
||||
'name'=>'host[host_username]',
|
||||
'value'=>$o->host_username ?? '',
|
||||
])
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-9 col-md-5 col-xl-5">
|
||||
@include('adminlte::widget.form_text',[
|
||||
'label'=>'Admin Password',
|
||||
'icon'=>'fas fa-lock',
|
||||
'id'=>'host_password',
|
||||
'old'=>'host.host_password',
|
||||
'name'=>'host[host_password]',
|
||||
'value'=>$o->host_password ?? '',
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section('page-scripts')
|
||||
@css(select2)
|
||||
@js(select2,autofocus)
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#tld_id').select2({
|
||||
dropdownAutoWidth: true,
|
||||
width: 'style',
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -0,0 +1,44 @@
|
||||
@use(App\Models\SupplierHostServer)
|
||||
|
||||
<!-- o=Service\Host::class -->
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-9 col-md-12 col-xl-7">
|
||||
<x-form.domain name="hosting" label="Domain Name" :name_value="$o->domain_name" :tld_value="$o->tld_id"/>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||
<x-leenooks::form.date id="expire_at" name="hosting[expire_at]" icon="fa-calendar" label="Expiry" old="hosting.expire_at" :value="($o->expire_at ?: $o->connect_at?->addMonths($o->contract_term))?->format('Y-m-d')"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<p class="h6">Hosting Details</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
|
||||
<x-leenooks::form.select id="supplier_host_server_id" name="hosting[supplier_host_server_id]" icon="fa-handshake" label="Registrar" :value="$o->supplier_host_server_id" :options="SupplierHostServer::active()->orderBy('name')->get()->transform(fn($item)=>['id'=>$item->id,'value'=>$item->name])"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-9 col-md-12 col-xl-7">
|
||||
<x-leenooks::form.text id="host_username" name="hosting[host_username]" icon="fa-user" label="Admin Username" :value="$o->host_username"/>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-9 col-md-5 col-xl-5">
|
||||
<x-leenooks::form.text id="host_password" name="hosting[host_password]" icon="fa-lock" label="Admin Password" :value="$o->host_password"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@pa(select2,autofocus)
|
||||
|
||||
@section('page-scripts')
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#tld_id').select2({
|
||||
dropdownAutoWidth: true,
|
||||
width: 'style',
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@append
|
9
resources/views/vendor/mail/html/button.blade.php
vendored
Normal file
9
resources/views/vendor/mail/html/button.blade.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<div style="margin: auto; text-align: center; padding-top: 20px;padding-bottom: 20px;">
|
||||
<div class="button">
|
||||
@isset($url)
|
||||
<a href="{{ $url }}">{{ $slot }}</a>
|
||||
@else
|
||||
{{ $slot }}
|
||||
@endisset
|
||||
</div>
|
||||
</div>
|
@ -1,3 +1 @@
|
||||
<div class="footer">
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
</div>
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
@ -1,6 +1,5 @@
|
||||
<div class="header">
|
||||
<div class="fixedw">
|
||||
<img src="{{ url($site->email_logo) }}"><br>
|
||||
<div class="subject">{{ $slot }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<img class="right" src="{{ url($site->email_logo) }}"><br>
|
||||
<div class="heading">{{ $slot }}</div>
|
||||
@if($subheading)
|
||||
<div class="subheading">{!! $subheading !!}</div>
|
||||
@endif
|
@ -1,25 +1,32 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="color-scheme" content="light only">
|
||||
<meta name="supported-color-schemes" content="light only">
|
||||
<link href='http://fonts.googleapis.com/css?family=Bree+Serif' rel='stylesheet' type='text/css'>
|
||||
<link href="http://fonts.googleapis.com/css?family=Roboto:400,300,100,500,700,900,400italic,300italic" rel="stylesheet" type="text/css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="color-scheme" content="light only">
|
||||
<meta name="supported-color-schemes" content="light only">
|
||||
{{--
|
||||
<link href='http://fonts.googleapis.com/css?family=Bree+Serif' rel='stylesheet' type='text/css'>
|
||||
--}}
|
||||
<link href="http://fonts.googleapis.com/css?family=Roboto:400,300,100,500,700,900,400italic,300italic" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{ $header ?? '' }}
|
||||
<section class="header">
|
||||
<div class="fixedw main-header">
|
||||
{{ $header ?? '' }}
|
||||
</div>
|
||||
</section>
|
||||
<section class="content">
|
||||
<div class="fixedw main-body">
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
</div>
|
||||
|
||||
<section class="content">
|
||||
<div class="fixedw main-body">
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
</div>
|
||||
|
||||
{{ $subcopy ?? '' }}
|
||||
</section>
|
||||
|
||||
{{ $footer ?? '' }}
|
||||
{{ $subcontent ?? '' }}
|
||||
</section>
|
||||
<section class="footer">
|
||||
<div class="fixedw main-footer">
|
||||
{{ $footer ?? '' }}
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
@ -1,7 +1,7 @@
|
||||
@component('mail::layout')
|
||||
{{-- Header --}}
|
||||
@slot('header')
|
||||
@component('mail::header',['site'=>$site])
|
||||
@component('mail::header',['site'=>$site,'subheading'=>$subheading ?? NULL])
|
||||
{{ $heading }}
|
||||
@endcomponent
|
||||
@endslot
|
||||
@ -9,11 +9,11 @@
|
||||
{{-- Body --}}
|
||||
{{ $slot }}
|
||||
|
||||
{{-- Subcopy --}}
|
||||
@isset($subcopy)
|
||||
@slot('subcopy')
|
||||
@component('mail::subcopy')
|
||||
{{ $subcopy }}
|
||||
{{-- Sub Content --}}
|
||||
@isset($subcontent)
|
||||
@slot('subcontent')
|
||||
@component('mail::subcontent')
|
||||
{{ $subcontent }}
|
||||
@endcomponent
|
||||
@endslot
|
||||
@endisset
|
||||
@ -21,11 +21,9 @@
|
||||
{{-- Footer --}}
|
||||
@slot('footer')
|
||||
@component('mail::footer')
|
||||
<div class="fixedw" style="text-align: right; font-size: 0.8em;">
|
||||
{{ config('mail.from.name') }}<br>
|
||||
{!! $site->address->join('<br>') !!}<br>
|
||||
{{ $site->site_email }}
|
||||
</div>
|
||||
@endcomponent
|
||||
@endslot
|
||||
@endcomponent
|
||||
@endcomponent
|
@ -1,9 +0,0 @@
|
||||
<div style="margin: auto; text-align: center; padding-bottom: 20px;">
|
||||
<div class="panel">
|
||||
@isset($url)
|
||||
<a href="{{ $url }}">{{ $slot }}</a>
|
||||
@else
|
||||
{{ $slot }}
|
||||
@endisset
|
||||
</div>
|
||||
</div>
|
@ -1,3 +1 @@
|
||||
<div class="light-box">
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
</div>
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
146
resources/views/vendor/mail/html/themes/default.css
vendored
146
resources/views/vendor/mail/html/themes/default.css
vendored
@ -1,88 +1,104 @@
|
||||
body{
|
||||
margin: 0 auto;
|
||||
font-family: 'Bree Serif';
|
||||
background: #f4f4f4;
|
||||
color: #6c7584;
|
||||
font-size: 1.2em;
|
||||
margin:0 auto;
|
||||
font-family:'Roboto', serif;
|
||||
color:#121212;
|
||||
font-size:1.0em;
|
||||
padding-top:20px;
|
||||
}
|
||||
.header{
|
||||
background: #232323;
|
||||
border-bottom: 5px solid #454d59;
|
||||
padding: 20px 0px 10px 0px;
|
||||
margin-bottom: 30px;
|
||||
color: #f4f4f4;
|
||||
font-weight: 300;
|
||||
margin-bottom:0;
|
||||
}
|
||||
.footer{
|
||||
background: #232323;
|
||||
border-top: 5px solid #454d59;
|
||||
padding: 10px 0px 20px 0px;
|
||||
margin-top: 30px;
|
||||
color: #f4f4f4;
|
||||
font-weight: 100;
|
||||
}
|
||||
.subject{
|
||||
font-weight: 300;
|
||||
font-family: 'Bree Serif',serif;
|
||||
font-size: 1.5em;
|
||||
/* text-align: right; */
|
||||
.main-header{
|
||||
background:#fafafa;
|
||||
border-top-left-radius:10px;
|
||||
border-top-right-radius:10px;
|
||||
color:#121212;
|
||||
font-weight:400;
|
||||
padding:10px 20px;
|
||||
border-top:1px solid #dbdbdb;
|
||||
border-right:1px solid #dbdbdb;
|
||||
border-left:1px solid #dbdbdb;
|
||||
}
|
||||
.panel{
|
||||
background:#454d59;
|
||||
border-radius: 10px;
|
||||
margin-top: 20px;
|
||||
padding: 20px;
|
||||
font-weight: 300;
|
||||
color: #f4f4f4;
|
||||
font-size: 1.4em;
|
||||
display: inline-block
|
||||
.main-header img{
|
||||
width:250px;
|
||||
}
|
||||
.light-box{
|
||||
background: #f9f9f9;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
font-weight: 300;
|
||||
margin-top: 10px;
|
||||
font-size: 0.8em;
|
||||
margin-bottom: 10px;
|
||||
.main-header .heading{
|
||||
font-weight:bold;
|
||||
font-size:1.4em;
|
||||
padding:5px 0;
|
||||
}
|
||||
.main-header .subheading{
|
||||
font-size:0.8em;
|
||||
padding:5px 0;
|
||||
}
|
||||
.main-body{
|
||||
background: #ffffff;
|
||||
border-radius: 10px;
|
||||
color:#6c7584;
|
||||
font-weight: 400;
|
||||
background:#ffffff;
|
||||
padding:10px 20px;
|
||||
border-top:1px solid #dbdbdb;
|
||||
border-left:1px solid #dbdbdb;
|
||||
border-right:1px solid #dbdbdb;
|
||||
border-bottom:3px solid #dbdbdb;
|
||||
border-bottom:1px solid #dbdbdb;
|
||||
}
|
||||
.main-body table{
|
||||
width: 100%;
|
||||
background:#fdfdfd;
|
||||
border-radius:10px;
|
||||
padding:10px;
|
||||
font-weight:300;
|
||||
margin-top:10px;
|
||||
font-size:0.8em;
|
||||
margin-bottom:10px;
|
||||
border: 1px dashed #dbdbdb
|
||||
}
|
||||
.main-body table thead td{
|
||||
font-weight: 300;
|
||||
border-bottom: 1px solid #dbdbdb;
|
||||
color: #ccc
|
||||
font-weight:300;
|
||||
border-bottom:1px solid #dbdbdb;
|
||||
}
|
||||
.main-body table td.title{
|
||||
font-size: 1.1em;
|
||||
line-height: 20px;
|
||||
font-size:1.1em;
|
||||
line-height:20px;
|
||||
color:#6c7584
|
||||
}
|
||||
.main-body table td.title small{
|
||||
font-weight: 300;
|
||||
font-size: 0.9em;
|
||||
color: #6c7584
|
||||
font-weight:300;
|
||||
font-size:0.9em;
|
||||
color:#6c7584
|
||||
}
|
||||
.main-body .note{
|
||||
font-size:0.8em;
|
||||
font-weight:300;
|
||||
font-style:normal;
|
||||
}
|
||||
.main-footer{
|
||||
background:#2f2f2f;
|
||||
border-bottom-left-radius:10px;
|
||||
border-bottom-right-radius:10px;
|
||||
color:#fefefe;
|
||||
padding:10px 20px;
|
||||
margin: 0 0 0 auto;
|
||||
border-bottom:1px solid #dbdbdb;
|
||||
border-right:1px solid #dbdbdb;
|
||||
border-left:1px solid #dbdbdb;
|
||||
font-size: 0.8em;
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
text-align: right;
|
||||
}
|
||||
.panel a{
|
||||
text-decoration: underline;
|
||||
color: #f4f4f4;
|
||||
.button{
|
||||
background:#2f2f2f;
|
||||
border-radius:5px;
|
||||
padding:10px;
|
||||
color:#fafafa;
|
||||
font-size:1em;
|
||||
display:inline-block
|
||||
}
|
||||
.panel a:hover{
|
||||
text-decoration: none;
|
||||
color: #ffffff;
|
||||
.button a{
|
||||
text-decoration:none;
|
||||
color:#fafafa;
|
||||
}
|
||||
.button a:hover{
|
||||
text-decoration:none;
|
||||
color:#ffffff;
|
||||
}
|
||||
|
||||
/* -- TO VALIDATE -- */
|
||||
@ -114,15 +130,17 @@ h3{
|
||||
color: #333;
|
||||
font-size:18px;
|
||||
}
|
||||
.links table td span, .links table td a{font-weight: 400}
|
||||
.border-l{border-left:1px solid #ccc}
|
||||
.links table td span, .links table td a{
|
||||
font-weight: 400
|
||||
}
|
||||
|
||||
.apikey{font-size: 18px; color:#333}
|
||||
.apikey p{border-bottom: 1px solid #dbdbdb; padding: 10px 0 10px 0;margin: 0 0;}
|
||||
.apikey p.last{border-bottom: none}
|
||||
.apikey small{font-size: 80%; font-weight: 300}
|
||||
.twitter{padding: 20px; font-weight: 300;font-size:16px;}
|
||||
.fixedw{width: 80%; margin: 0 auto;}
|
||||
.right{float:right}
|
||||
.left{float:left}
|
||||
.clear{clear: both;}
|
||||
table thead td {font-size: 16px;}
|
||||
|
||||
pre {white-space:pre-wrap;}
|
1
resources/views/vendor/mail/text/subcontent.blade.php
vendored
Normal file
1
resources/views/vendor/mail/text/subcontent.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{ $slot }}
|
@ -61,8 +61,6 @@ Route::get('pay/paypal/capture',[PaypalController::class,'capture']);
|
||||
Route::get('auth/{socialProvider}',[SocialLoginController::class,'redirectToProvider']);
|
||||
Route::get('auth/{socialProvider}/callback',[SocialLoginController::class,'handleProviderCallback']);
|
||||
Route::get('auth/{socialProvider}/token',[SocialLoginController::class,'handleBearerTokenCallback']);
|
||||
Route::get('auth/{socialProvider}/link',[SocialLoginController::class,'link']);
|
||||
Route::post('auth/{socialProvider}/linkcomplete',[SocialLoginController::class,'linkcomplete']);
|
||||
|
||||
// Return from user switch
|
||||
Route::get('admin/switch/stop',[SwitchUserController::class,'switch_stop'])
|
||||
|
Loading…
x
Reference in New Issue
Block a user