Compare commits

...

2 Commits

Author SHA1 Message Date
2512182910 Update service update to use components, enhanced form handling and submission. Added pppoe to broadband and changed validation to allow for longer service number.
All checks were successful
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 31s
Create Docker Image / Final Docker Image Manifest (push) Successful in 9s
2024-07-24 14:14:11 +10:00
46075745d2 Move user suppliers to account suppliers 2024-07-24 09:32:17 +10:00
17 changed files with 501 additions and 332 deletions

View File

@ -12,13 +12,14 @@ use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
use Illuminate\View\View; use Illuminate\View\View;
use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\HttpException;
use App\Http\Requests\ServiceChangeRequest; use App\Http\Requests\ServiceChangeRequest;
use App\Mail\{CancelRequest,ChangeRequest}; use App\Mail\{CancelRequest,ChangeRequest};
use App\Models\{Charge,Product,Service}; use App\Models\{Charge,Invoice,Product,Service};
class ServiceController extends Controller class ServiceController extends Controller
{ {
@ -415,39 +416,74 @@ class ServiceController extends Controller
*/ */
public function update(Request $request,Service $o) public function update(Request $request,Service $o)
{ {
if ($o->type->validation()) { Session::put('service_update',true);
Session::put('service_update',true);
$validator = Validator::make($x=$request->post($o->category),$o->type->validation());
if ($validator->fails()) { // We dynamically create our validation
return redirect() $validator = Validator::make(
->back() $request->post(),
->withErrors($validator) $x=collect($o->type->validation())
->withInput(); ->keys()
} ->transform(fn($item)=>sprintf('%s.%s',$o->category,$item))
->combine(array_values($o->type->validation()))
->transform(fn($item)=>is_string($item)
? preg_replace('/^exclude_without:/',sprintf('exclude_without:%s.',$o->category),$item)
: $item)
->merge(
[
'external_billing' => 'nullable|in:on',
'suspend_billing' => 'nullable|in:on',
'recur_schedule' => ['required',Rule::in(collect(Invoice::billing_periods)->keys())],
'invoice_next_at' => 'nullable|date',
'price' => 'nullable|numeric',
$o->category => 'array|min:1',
]
)
->toArray()
);
$o->type->forceFill($validator->validated()); if ($validator->fails()) {
return redirect()
->back()
->withErrors($validator)
->withInput();
}
} elseif ($request->post($o->product->category)) { $validated = collect($validator->validated());
$o->type->forceFill($request->post($o->product->category));
// Store our service type values
$o->type->forceFill($validated->get($o->category));
// Some special handling
switch ($o->category) {
case 'broadband':
// If pppoe is not set, then we dont need username/password
$o->type->pppoe = ($x=data_get($validated,$o->category.'.pppoe',FALSE));
if (! $x) {
$o->type->service_username = NULL;
$o->type->service_password = NULL;
}
break;
} }
$o->type->save(); $o->type->save();
if ($request->post('invoice_next_at')) if ($validated->has('invoice_next_at'))
$o->invoice_next_at = $request->invoice_next_at; $o->invoice_next_at = $validated->get('invoice_next_at');
if ($request->post('recur_schedule')) if ($validated->has('recur_schedule'))
$o->recur_schedule = $request->recur_schedule; $o->recur_schedule = $validated->get('recur_schedule');
$o->suspend_billing = ($request->suspend_billing == 'on'); $o->suspend_billing = ($validated->get('suspend_billing') == 'on');
$o->external_billing = ($request->external_billing == 'on'); $o->external_billing = ($validated->get('external_billing') == 'on');
$o->price = $request->price ?: NULL; $o->price = $validated->get('price');
// Also update our service start_at date. // Also update our service start_at date.
// @todo We may want to make start_at/stop_at dynamic values calculated by the type records // @todo We may want to make start_at/stop_at dynamic values calculated by the type records
if ($request->post('start_at')) if ($validated->has('start_at'))
$o->start_at = $request->start_at; $o->start_at = $validated->get('start_at');
else { else {
// For broadband, start_at is connect_at in the type record // For broadband, start_at is connect_at in the type record
switch ($o->category) { switch ($o->category) {
@ -459,6 +495,8 @@ class ServiceController extends Controller
$o->save(); $o->save();
return redirect()->back()->with('success','Record Updated'); return redirect()
->back()
->with('success','Record Updated');
} }
} }

View File

@ -4,14 +4,12 @@ namespace App\Http\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
use Illuminate\Validation\Rule;
use App\Http\Requests\UserEdit; use App\Http\Requests\{AccountSupplierAdd,UserEdit};
use App\Models\{Supplier,User}; use App\Models\{Account,Supplier,User};
class UserController extends Controller class UserController extends Controller
{ {
@ -38,23 +36,15 @@ class UserController extends Controller
/** /**
* Add a supplier to a user's profile * Add a supplier to a user's profile
* *
* @param Request $request * @param AccountSupplierAdd $request
* @param User $o * @param Account $o
* @return \Illuminate\Http\RedirectResponse * @return RedirectResponse
*/ */
public function supplier_addedit(Request $request,User $o) public function supplier_addedit(AccountSupplierAdd $request,Account $o): RedirectResponse
{ {
Session::put('supplier_update',true);
$validated = $request->validate([
'id'=> ['required','string',Rule::unique('supplier_user')->where(fn ($query) => $query->where('supplier_id',$request->supplier_id)->where('user_id','<>',$o->id))],
'supplier_id'=>'required|exists:suppliers,id',
]);
$o->suppliers()->attach([ $o->suppliers()->attach([
$validated['supplier_id'] => [ $request->validated('supplier_id') => [
'id'=>$validated['id'], 'supplier_ref'=>$request->validated('supplier_ref'),
'site_id'=>$o->site_id,
'created_at'=>Carbon::now(), 'created_at'=>Carbon::now(),
] ]
]); ]);
@ -67,13 +57,13 @@ class UserController extends Controller
/** /**
* Remove a supplier from a user's profile * Remove a supplier from a user's profile
* *
* @param User $o * @param Account $o
* @param Supplier $so * @param Supplier $so
* @return \Illuminate\Http\RedirectResponse * @return RedirectResponse
*/ */
public function supplier_delete(User $o,Supplier $so) public function supplier_delete(Account $o,Supplier $so): RedirectResponse
{ {
Session::put('supplier_update',true); Session::put('supplier_update',TRUE);
$o->suppliers()->detach([$so->id]); $o->suppliers()->detach([$so->id]);

View File

@ -0,0 +1,42 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Session;
use Illuminate\Validation\Rule;
class AccountSupplierAdd extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return Gate::allows('wholesaler');
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
Session::put('supplier_update',true);
return [
'supplier_ref'=> [
'required',
'string',
'min:2',
Rule::unique('account_supplier')
->where(fn($query)=>$query
->where('account_id',request()->get('account_id')))
->where('supplier_id',request()->get('supplier_id')),
],
'supplier_id'=>'required|exists:suppliers,id',
];
}
}

View File

@ -159,6 +159,15 @@ class Account extends Model implements IDs
->active(); ->active();
} }
/**
* Supplier configuration for this account
*/
public function suppliers()
{
return $this->belongsToMany(Supplier::class)
->withPivot('supplier_ref','created_at');
}
/** /**
* Taxes applicable for this account * Taxes applicable for this account
*/ */

View File

@ -88,10 +88,11 @@ class Broadband extends Type implements ServiceUsage
public function validation(): array public function validation(): array
{ {
return [ return [
'service_number' => 'nullable|string|min:10|max:10', 'service_number' => 'nullable|string|min:10|max:11',
'service_address' => 'nullable|string|min:3', 'service_address' => 'nullable|string|min:5',
'service_username' => 'nullable|string', 'service_username' => 'exclude_without:pppoe|nullable|string|min:3',
'service_password' => 'nullable|string', 'service_password' => 'exclude_without:pppoe|nullable|string|min:8',
'pppoe' => 'nullable|in:on',
'connect_at' => 'nullable|date', 'connect_at' => 'nullable|date',
'start_at' => 'nullable|date', 'start_at' => 'nullable|date',
'expire_at' => 'nullable|date|after:start_at', 'expire_at' => 'nullable|date|after:start_at',

View File

@ -132,17 +132,6 @@ class User extends Authenticatable implements IDs
return $this->hasOneThrough(Rtm::class,Account::class); return $this->hasOneThrough(Rtm::class,Account::class);
} }
/**
* Supplier configuration for this user
*
* @deprecated To move to account->suppliers()
*/
public function suppliers()
{
return $this->belongsToMany(Supplier::class)
->withPivot('id','created_at');
}
/* ATTRIBUTES */ /* ATTRIBUTES */
/** /**

26
composer.lock generated
View File

@ -1534,16 +1534,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v11.16.0", "version": "v11.17.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "bd4808aaf103ccb5cb4b00bcee46140c070c0ec4" "reference": "42f505a0c8afc0743f73e70bec08e641e2870bd6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/bd4808aaf103ccb5cb4b00bcee46140c070c0ec4", "url": "https://api.github.com/repos/laravel/framework/zipball/42f505a0c8afc0743f73e70bec08e641e2870bd6",
"reference": "bd4808aaf103ccb5cb4b00bcee46140c070c0ec4", "reference": "42f505a0c8afc0743f73e70bec08e641e2870bd6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1736,7 +1736,7 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2024-07-16T14:33:07+00:00" "time": "2024-07-23T16:33:27+00:00"
}, },
{ {
"name": "laravel/intuit", "name": "laravel/intuit",
@ -1777,16 +1777,16 @@
}, },
{ {
"name": "laravel/passport", "name": "laravel/passport",
"version": "v12.2.0", "version": "v12.2.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/passport.git", "url": "https://github.com/laravel/passport.git",
"reference": "b24c6462835a16163141fbe588533d16603212b7" "reference": "795bbb406c8f10167df6062032de803bd7d686f2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/passport/zipball/b24c6462835a16163141fbe588533d16603212b7", "url": "https://api.github.com/repos/laravel/passport/zipball/795bbb406c8f10167df6062032de803bd7d686f2",
"reference": "b24c6462835a16163141fbe588533d16603212b7", "reference": "795bbb406c8f10167df6062032de803bd7d686f2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1849,7 +1849,7 @@
"issues": "https://github.com/laravel/passport/issues", "issues": "https://github.com/laravel/passport/issues",
"source": "https://github.com/laravel/passport" "source": "https://github.com/laravel/passport"
}, },
"time": "2024-04-17T17:56:14+00:00" "time": "2024-07-10T19:25:36+00:00"
}, },
{ {
"name": "laravel/prompts", "name": "laravel/prompts",
@ -3056,11 +3056,11 @@
}, },
{ {
"name": "leenooks/laravel", "name": "leenooks/laravel",
"version": "11.1.2", "version": "11.1.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://gitea.dege.au/laravel/leenooks.git", "url": "https://gitea.dege.au/laravel/leenooks.git",
"reference": "f32c29fa8c4b189add48bde26b7b7115be49355f" "reference": "f393813311b912f77e4a7082498ed7511482b531"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -3093,7 +3093,7 @@
"laravel", "laravel",
"leenooks" "leenooks"
], ],
"time": "2024-07-23T08:47:36+00:00" "time": "2024-07-24T04:08:04+00:00"
}, },
{ {
"name": "leenooks/passkey", "name": "leenooks/passkey",

View File

@ -0,0 +1,47 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('supplier_user', function (Blueprint $table) {
$table->string('supplier_ref')->nullable();
$table->dropUnique(['id','site_id']);
$table->dropUnique(['id','supplier_id']);
$table->unique(['user_id','supplier_ref']);
});
DB::update('UPDATE supplier_user set supplier_ref=id');
DB::update('ALTER TABLE supplier_user ALTER COLUMN supplier_ref SET NOT NULL');
Schema::table('supplier_user', function (Blueprint $table) {
$table->dropColumn('id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('supplier_user', function (Blueprint $table) {
$table->string('id')->nullable();
$table->unique(['id','site_id']);
$table->unique(['id','supplier_id']);
$table->dropUnique(['user_id','supplier_ref']);
});
DB::update('UPDATE supplier_user set id=supplier_ref');
Schema::table('supplier_user', function (Blueprint $table) {
$table->dropColumn('supplier_ref');
});
}
};

View File

@ -0,0 +1,52 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('account_supplier', function (Blueprint $table) {
$table->timestamps();
$table->integer('supplier_id')->unsigned();
$table->integer('account_id')->unsigned();
$table->string('supplier_ref');
$table->boolean('active')->default(FALSE);
$table->unique(['account_id','supplier_id']);
$table->unique(['supplier_id','supplier_ref']);
$table->foreign('account_id')->references('id')->on('accounts');
$table->foreign('supplier_id')->references('id')->on('suppliers');
});
foreach (DB::table('supplier_user')->cursor() as $o) {
$ao = \App\Models\Account::where('user_id',$o->user_id)->firstOrfail();
DB::table('account_supplier')
->insert([
'created_at' => $o->created_at,
'updated_at' => $o->updated_at,
'supplier_id' => $o->supplier_id,
'account_id' => $ao->id,
'supplier_ref' => $o->supplier_ref,
'active' => $o->active,
]);
}
Schema::drop('supplier_user');
}
/**
* Reverse the migrations.
*/
public function down(): void
{
abort(500,'Cant go back');
}
};

View File

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('service_broadband', function (Blueprint $table) {
$table->boolean('pppoe')->default(FALSE);
});
DB::table('service_broadband')->update(['pppoe'=>TRUE]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('service_broadband', function (Blueprint $table) {
$table->dropColumn('pppoe');
});
}
};

View File

@ -0,0 +1,59 @@
<!-- $o=Account::class -->
@use(App\Models\Supplier)
<!-- Suppliers Configuration for this User -->
<div class="row">
<div class="col-6">
<div class="card">
<div class="card-body">
<x-leenooks::button.success class="float-right"/>
<table class="table">
<thead>
<tr>
<th>Supplier</th>
<th>ID</th>
<th>Added</th>
</tr>
</thead>
<tbody>
@foreach ($o->suppliers as $so)
<tr>
<td>{{ $so->name }}</td>
<td>{{ $so->pivot->supplier_ref }}</td>
<td>{{ $so->pivot->created_at }} <a class="float-right" href="{{ url('a/account/supplier/delete',[$o->id,$so->id]) }}"><i class="fas fa-fw fa-trash"></i></a></td>
</tr>
@endforeach
</tbody>
@if(($x=Supplier::active()->whereNotIn('id',$o->suppliers->pluck('id'))->orderBy('name')->get())->count())
<tfoot>
<tr>
<td colspan="3">
<form method="POST" action="{{ url('a/account/supplier/add',[$o->id]) }}">
@csrf
<div class="row">
<div class="col-6">
<x-leenooks::form.select id="supplier_id" name="supplier_id" icon="fa-handshake" label="Add Supplier" :options="$x->map(function($item) { $item->value = $item->name; return $item; })->toArray()"/>
</div>
<div class="col-4">
<x-leenooks::form.text id="supplier_ref" name="supplier_ref" icon="fa-hashtag" label="ID"/>
</div>
<div class="col-2">
<x-leenooks::button.submit class="float-right">Save</x-leenooks::button.submit>
</div>
</div>
</form>
</td>
</tr>
</tfoot>
@endif
</table>
</div>
</div>
</div>
</div>

View File

@ -22,7 +22,7 @@
<div class="card card-light card-tabs"> <div class="card card-light card-tabs">
<div class="card-header p-0 pt-1"> <div class="card-header p-0 pt-1">
<ul class="nav nav-tabs" id="accounts-tab" role="tablist"> <ul class="nav nav-tabs" id="accounts-tab">
<li class="pt-2 px-3"><h3 class="card-title">Accounts</h3></li> <li class="pt-2 px-3"><h3 class="card-title">Accounts</h3></li>
@foreach($o->accounts as $ao) @foreach($o->accounts as $ao)
<li class="nav-item"> <li class="nav-item">
@ -43,16 +43,16 @@
<div class="card-body"> <div class="card-body">
<div class="tab-content" id="accounts-tab-content"> <div class="tab-content" id="accounts-tab-content">
@foreach($o->accounts as $ao) @foreach($o->accounts as $ao)
<div class="tab-pane fade @if(! $loop->index)show active @endif" id="account_{{ $ao->id }}" role="tabpanel" aria-labelledby="account_{{ $ao->id }}"> <div @class(['tab-pane','fade','show active'=>! $loop->index]) id="account_{{ $ao->id }}" aria-labelledby="account_{{ $ao->id }}">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<div class="card-header bg-white"> <div class="card-header bg-white">
<ul class="nav nav-pills"> <ul class="nav nav-pills">
<li class="nav-item"><a class="nav-link {{ (! session()->has('supplier_update')) ? 'active' : '' }}" href="#tab-services" data-toggle="tab">Services</a></li> <li class="nav-item"><a @class(['nav-link','active'=>! session()->has('supplier_update')]) href="#tab-services" data-toggle="tab">Services</a></li>
<li class="nav-item"><a class="nav-link" href="#tab-futureinvoice" data-toggle="tab">Future Invoice</a></li> <li class="nav-item"><a class="nav-link" href="#tab-futureinvoice" data-toggle="tab">Future Invoice</a></li>
@canany('reseller','wholesaler') @canany('reseller','wholesaler')
<li class="nav-item ml-auto"> <li class="nav-item ml-auto">
<a class="nav-link {{ session()->has('supplier_update') ? 'active' : '' }}" href="#tab-supplier" data-toggle="tab">Supplier</a> <a @class(['nav-link','active'=>session()->has('supplier_update')]) href="#tab-supplier" data-toggle="tab">Supplier</a>
</li> </li>
@endcanany @endcanany
</ul> </ul>
@ -60,7 +60,7 @@
<div class="card-body pl-0 pr-0"> <div class="card-body pl-0 pr-0">
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane {{ (! session()->has('supplier_update')) ? 'active' : '' }}" id="tab-services"> <div @class(['tab-pane','fade','show active'=>! session()->has('supplier_update')]) id="tab-services">
<div class="row"> <div class="row">
<div class="col-12 col-xl-7"> <div class="col-12 col-xl-7">
@include('theme.backend.adminlte.account.widget.service_active',['o'=>$ao]) @include('theme.backend.adminlte.account.widget.service_active',['o'=>$ao])
@ -73,7 +73,7 @@
</div> </div>
</div> </div>
<div class="tab-pane" id="tab-futureinvoice"> <div class="tab-pane fade" id="tab-futureinvoice">
<div class="row"> <div class="row">
<div class="col-12 col-xl-9"> <div class="col-12 col-xl-9">
@include('theme.backend.adminlte.invoice.widget.next',['future'=>TRUE]) @include('theme.backend.adminlte.invoice.widget.next',['future'=>TRUE])
@ -82,8 +82,8 @@
</div> </div>
@canany('reseller','wholesaler') @canany('reseller','wholesaler')
<div class="tab-pane {{ session()->pull('supplier_update') ? 'active' : '' }}" id="tab-supplier" role="tabpanel"> <div @class(['tab-pane','fade','show active'=>session()->pull('supplier_update')]) id="tab-supplier">
@include('theme.backend.adminlte.user.widget.supplier') @include('theme.backend.adminlte.account.widget.supplier',['o'=>$ao])
</div> </div>
@endcanany @endcanany
</div> </div>
@ -95,7 +95,7 @@
@if($o==$user) @if($o==$user)
@canany('reseller','wholesaler') @canany('reseller','wholesaler')
<div class="tab-pane" id="tab-reseller" role="tabpanel"> <div class="tab-pane fade" id="tab-reseller">
@include('theme.backend.adminlte.widget.admin.reseller') @include('theme.backend.adminlte.widget.admin.reseller')
</div> </div>
@endcanany @endcanany

View File

@ -1,3 +1,5 @@
@use(App\Models\Product)
@extends('adminlte::layouts.app') @extends('adminlte::layouts.app')
@section('htmlheader_title') @section('htmlheader_title')
@ -26,25 +28,18 @@
<div class="card"> <div class="card">
<div class="card-header bg-dark d-flex p-0"> <div class="card-header bg-dark d-flex p-0">
<ul class="nav nav-pills w-100 p-2"> <ul class="nav nav-pills w-100 p-2">
{{-- @if ($x=! ($o->suspend_billing || $o->external_billing))
<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','active'=>! session()->has('service_update')]) href="#pending_items" data-toggle="tab">Pending Items</a></li>
<li class="nav-item"><a class="nav-link" href="#traffic" data-toggle="tab">Traffic</a></li> @endif
--}}
@if (! $o->suspend_billing AND ! $o->external_billing) @if ($o->product->hasUsage())
<li class="nav-item"><a class="nav-link {{ (! session()->has('service_update')) ? 'active' : '' }}" href="#pending_items" data-toggle="tab">Pending Items</a></li> <li class="nav-item"><a @class(['nav-link','active'=>! ($x || session()->has('service_update'))]) href="#traffic" data-toggle="tab">Traffic</a></li>
@endif
@if ($o->product->hasUsage())
<li class="nav-item"><a class="nav-link {{ (! $o->isBilled() && (! session()->has('service_update'))) ? 'active' : '' }}" href="#traffic" data-toggle="tab">Traffic</a></li>
@endif @endif
{{--
<li class="nav-item"><a class="nav-link" href="#invoices" data-toggle="tab">Invoices</a></li>
<li class="nav-item"><a class="nav-link" href="#emails" data-toggle="tab">Emails</a></li>
--}}
@can('wholesaler') @can('wholesaler')
<li class="nav-item ml-auto"><a class="nav-link" href="#billing" data-toggle="tab">Billing History</a></li> <li class="nav-item ml-auto"><a class="nav-link" href="#billing" data-toggle="tab">Billing History</a></li>
<li class="nav-item"><a class="nav-link" href="#internal" data-toggle="tab">Internal</a></li> <li class="nav-item"><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> <li class="nav-item"><a @class(['nav-link','active'=>session()->has('service_update')]) href="#update" data-toggle="tab">Update</a></li>
@endcan @endcan
</ul> </ul>
@ -54,58 +49,51 @@
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#">ACTION <span class="caret"></span></a> <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#">ACTION <span class="caret"></span></a>
<div class="dropdown-menu dropdown-menu-right"> <div class="dropdown-menu dropdown-menu-right">
@foreach($o->actions() as $stage => $title) @foreach($o->actions() as $stage => $title)
<a class="dropdown-item" tabindex="-1" href="{{ url('u/service',['id'=>$o->id,'action'=>'change','stage'=>$stage]) }}">{{ $title }}</a> <a class="dropdown-item" tabindex="-1" href="{{ url('u/service',['id'=>$o->id,'action'=>'change','stage'=>$stage]) }}">{{ $title }}</a>
@endforeach @endforeach
{{-- <div class="dropdown-divider"></div> --}} {{-- <div class="dropdown-divider"></div> --}}
</div> </div>
</li> </li>
</ul> </ul>
@endcan @endcan
</div><!-- /.card-header --> </div>
<div class="card-body"> <div class="card-body">
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane fade" id="product" role="tabpanel"> @if ($x=! ($o->suspend_billing || $o->external_billing))
Product. <div @class(['tab-pane','fade','show active'=>! session()->has('service_update')]) id="pending_items">
</div>
@if (! $o->suspend_billing AND ! $o->external_billing)
<div class="tab-pane fade {{ (! session()->has('service_update')) ? 'active show' : '' }}" id="pending_items" role="tabpanel">
@include('theme.backend.adminlte.service.widget.invoice') @include('theme.backend.adminlte.service.widget.invoice')
</div> </div>
@endif @endif
@if ($o->product->hasUsage()) @if ($o->product->hasUsage())
<div class="tab-pane fade {{ (! $o->isBilled() && (! session()->has('service_update'))) ? 'active show' : '' }}" id="traffic" role="tabpanel"> <div @class(['tab-pane','fade','show active'=>! ($x || session()->has('service_update'))]) id="traffic">
@if ($o->type->usage(30)->count()) @if ($o->type->usage(30)->count())
@include('theme.backend.adminlte.service.widget.'.$o->product->category.'.usagegraph',['o'=>$o->type]) @include('theme.backend.adminlte.service.widget.'.$o->product->category.'.usagegraph',['o'=>$o->type])
@endif @endif
</div> </div>
@endif @endif
<div class="tab-pane fade" id="invoices" role="tabpanel">
Invoices.
</div>
<div class="tab-pane fade" id="emails" role="tabpanel">
Email.
</div>
@can('wholesaler') @can('wholesaler')
<div class="tab-pane fade" id="billing" role="tabpanel"> <div class="tab-pane fade" id="billing">
@include('theme.backend.adminlte.service.widget.billinghistory',['o'=>$o]) @include('theme.backend.adminlte.service.widget.billinghistory',['o'=>$o])
</div> </div>
<div class="tab-pane fade" id="internal" role="tabpanel">
<div class="tab-pane fade" id="internal">
@if(($x=$o->changes()->where('service__change.active',TRUE)->where('complete',FALSE)->get()->pop())) @if(($x=$o->changes()->where('service__change.active',TRUE)->where('complete',FALSE)->get()->pop()))
@include('theme.backend.adminlte.service.widget.internal',['o'=>$o,'p'=>$x]) @include('theme.backend.adminlte.service.widget.internal',['o'=>$o,'p'=>$x])
@else @else
@include('theme.backend.adminlte.service.widget.internal',['o'=>$o,'p'=>new \App\Models\Product()]) @include('theme.backend.adminlte.service.widget.internal',['o'=>$o,'p'=>new Product()])
@endif @endif
</div> </div>
<div class="tab-pane fade {{ session()->pull('service_update') ? 'active show' : '' }}" id="update" role="tabpanel"> <div @class(['tab-pane','fade','show active'=>session()->has('service_update')]) id="update">
@include('theme.backend.adminlte.service.widget.update') @include('theme.backend.adminlte.service.widget.update')
</div> </div>
@endcan @endcan
</div> </div>
</div> </div>
<!-- /.card -->
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,49 +1,28 @@
<!-- $o=Service\Broadband::class --> <!-- $o=Service\Broadband::class -->
<div class="row"> <div class="row">
<div class="col-12 col-sm-9 col-md-6 col-xl-5"> <div class="col-12 col-sm-9 col-md-6 col-xl-5">
@include('adminlte::widget.form_text',[ <x-leenooks::form.text id="service_number" name="broadband[service_number]" icon="fa-phone" label="Service Number" old="broadband.service_number" :value="$o->service_number"/>
'label'=>'Service Number',
'icon'=>'fas fa-phone',
'id'=>'service_number',
'old'=>'broadband.service_number',
'name'=>'broadband[service_number]',
'value'=>$o->service_number ?? '',
])
</div> </div>
<div class="col-12 col-sm-9 col-md-6 col-xl-7"> <div class="col-12 col-sm-9 col-md-6 col-xl-7">
@include('adminlte::widget.form_text',[ <x-leenooks::form.text id="service_address" name="broadband[service_address]" icon="fa-map" label="Service Address" old="broadband.service_address" :value="$o->service_address"/>
'label'=>'Service Address', </div>
'icon'=>'fas fa-map', </div>
'id'=>'service_address',
'old'=>'broadband.service_address', <div class="row">
'name'=>'broadband[service_address]', <div class="col">
'value'=>$o->service_address ?? '', Connection Type
]) <x-leenooks::form.toggle id="pppoe" name="broadband[pppoe]" label="PPPoE" old="broadband.pppoe" :value="$o->pppoe"/>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-12 col-sm-9 col-md-12 col-xl-7"> <div class="col-12 col-sm-9 col-md-12 col-xl-7">
@include('adminlte::widget.form_text',[ <x-leenooks::form.text id="service_username" name="broadband[service_username]" icon="fa-user" label="Service Username" old="broadband.service_username" :value="$o->service_username"/>
'label'=>'Service Username',
'icon'=>'fas fa-user',
'id'=>'service_username',
'old'=>'broadband.service_username',
'name'=>'broadband[service_username]',
'value'=>$o->service_username ?? '',
])
</div> </div>
<div class="col-12 col-sm-9 col-md-5 col-xl-5"> <div class="col-12 col-sm-9 col-md-5 col-xl-5">
@include('adminlte::widget.form_text',[ <x-leenooks::form.text id="service_password" name="broadband[service_password]" icon="fa-lock" label="Service Password" old="broadband.service_password" :value="$o->service_password"/>
'label'=>'Service Password',
'icon'=>'fas fa-lock',
'id'=>'service_password',
'old'=>'broadband.service_password',
'name'=>'broadband[service_password]',
'value'=>$o->service_password ?? '',
])
</div> </div>
</div> </div>
@ -52,25 +31,11 @@
<div class="row"> <div class="row">
<div class="col-12 col-sm-9 col-md-6 col-xl-5"> <div class="col-12 col-sm-9 col-md-6 col-xl-5">
@include('adminlte::widget.form_date',[ <x-leenooks::form.date id="connect_at" name="broadband[connect_at]" icon="fa-calendar" label="Connect Date" old="broadband.connect_at" :value="$o->connect_at?->format('Y-m-d')"/>
'label'=>'Connect Date',
'icon'=>'fas fa-calendar',
'id'=>'connect_at',
'old'=>'broadband.connect_at',
'name'=>'broadband[connect_at]',
'value'=>$o->connect_at ? $o->connect_at->format('Y-m-d') : '',
])
</div> </div>
<div class="col-12 col-sm-9 col-md-6 col-xl-5"> <div class="col-12 col-sm-9 col-md-6 col-xl-5">
@include('adminlte::widget.form_date',[ <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'))"/>
'label'=>'Contract End',
'icon'=>'fas fa-calendar',
'id'=>'expire_at',
'old'=>'broadband.expire_at',
'name'=>'broadband[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>
</div> </div>
@ -78,26 +43,39 @@
<p class="h6">IP Address</p> <p class="h6">IP Address</p>
<div class="row"> <div class="row">
<div class="col-12 col-lg-5"> <div class="col-12 col-lg-5">
@include('adminlte::widget.form_text',[ <x-leenooks::form.text id="ipaddress" name="broadband[ipaddress]" icon="fa-map-marker" label="IPv4 Address" old="broadband.ipaddress" :value="$o->ipaddress"/>
'label'=>'IPv4 Address',
'icon'=>'fas fa-map-marker',
'id'=>'ipaddress',
'old'=>'broadband.ipaddress',
'name'=>'broadband[ipaddress]',
'value'=>$o->ipaddress ?? '',
])
</div> </div>
<div class="col-12 col-lg-7"> <div class="col-12 col-lg-7">
<div class="form-group"> <div class="form-group">
@include('adminlte::widget.form_text',[ <x-leenooks::form.text id="ip6address" name="broadband[ip6address]" icon="fa-map-marker-alt" label="IPv6 Address" :value="$o->ip6address"/>
'label'=>'IPv6 Address',
'icon'=>'fas fa-map-marker-alt',
'id'=>'ip6address',
'old'=>'broadband.ip6address',
'name'=>'broadband[ip6address]',
'value'=>$o->ip6address ?? '',
])
</div> </div>
</div> </div>
</div> </div>
@section('page-scripts')
<script type="text/javascript">
function toggle_pppoe(item) {
if (item.is(':checked')) {
$('#service_username').closest('.form-group').parent().removeClass('d-none');
$('#service_password').closest('.form-group').parent().removeClass('d-none');
item.closest('.form-group').removeClass('mb-0');
} else {
$('#service_username').closest('.form-group').parent().addClass('d-none');
$('#service_password').closest('.form-group').parent().addClass('d-none');
item.closest('.form-group').addClass('mb-0');
}
}
$(document).ready(function() {
toggle_pppoe($('#pppoe'));
$('#pppoe').on('click',function(item) {
toggle_pppoe($(this));
});
});
</script>
@append

View File

@ -1,56 +1,30 @@
<!-- $o=Service::class -->
@use(App\Models\Invoice)
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h4>Update Service details</h4> <h4>Update Service details <x-leenooks::button.success class="float-right"/></h4>
<hr>
<form class="g-0 needs-validation" method="POST" action="{{ url('a/service/update',[$o->id]) }}">
@include('adminlte::widget.success')
<form method="POST" action="{{ url('a/service/update',[$o->id]) }}">
@csrf @csrf
<div class="row"> <div class="row">
<!-- External Billing --> <!-- External Billing -->
<div class="col-2"> <div class="col-2">
@include('adminlte::widget.form_toggle',[ <x-leenooks::form.toggle id="external_billing" name="external_billing" label="External Billing" :value="$o->external_billing"/>
'label'=>'External Billing', <x-leenooks::form.toggle id="suspend_billing" name="suspend_billing" label="Suspend Billing" :value="$o->suspend_billing"/>
'id'=>'external_billing',
'old'=>'external_billing',
'name'=>'external_billing',
'value'=>$o->external_billing ?? '',
])
<!-- Suspend Billing -->
@include('adminlte::widget.form_toggle',[
'label'=>'Suspend Billing',
'id'=>'suspend_billing',
'old'=>'suspend_billing',
'name'=>'suspend_billing',
'value'=>$o->suspend_billing ?? '',
])
</div> </div>
<div class="col-1"></div> <div class="col-1"></div>
<div class="col-12 col-sm-9 col-md-6 col-xl-5"> <div class="col-12 col-sm-9 col-md-6 col-xl-5">
@include('adminlte::widget.form_date',[ <x-leenooks::form.date id="invoice_next_at" name="invoice_next_at" icon="fa-calendar" label="Billing Start Date" :value="($o->invoice_next_at ?: $o->connect_at)?->format('Y-m-d')"/>
'label'=>'Billing Start Date',
'icon'=>'fas fa-calendar',
'id'=>'invoice_next_at',
'old'=>'invoice_next_at',
'name'=>'invoice_next_at',
'value'=>$o->invoice_next_at ? $o->invoice_next_at->format('Y-m-d') : ($o->connect_at ? $o->connect_at->format('Y-m-d') : ''),
])
</div> </div>
<!-- Price --> <!-- Price -->
<div class="col-12 col-sm-9 col-md-12 col-xl-3"> <div class="col-12 col-sm-9 col-md-12 col-xl-3">
@include('adminlte::widget.form_text',[ <x-leenooks::form.text name="price" icon="fa-dollar-sign" label="Price" :value="$o->price"/>
'label'=>'Price',
'icon'=>'fas fa-dollar-sign',
'id'=>'price',
'old'=>'price',
'name'=>'price',
'value'=>$o->price ?? '',
])
</div> </div>
</div> </div>
@ -58,15 +32,7 @@
<div class="col-3"></div> <div class="col-3"></div>
<div class="col-12 col-sm-9 col-md-6 col-xl-5"> <div class="col-12 col-sm-9 col-md-6 col-xl-5">
@include('adminlte::widget.form_select',[ <x-leenooks::form.select id="recur_schedule" name="recur_schedule" icon="fa-redo" label="Renew Term" :value="$o->recur_schedule" :options="collect(Invoice::billing_periods)->map(fn($item,$key)=>['id'=>$key,'value'=>$item['name']])"/>
'label'=>'Renew Term',
'icon'=>'fas fa-redo',
'id'=>'recur_schedule',
'old'=>'recur_schedule',
'name'=>'recur_schedule',
'options'=>collect(\App\Models\Invoice::billing_periods)->transform(function($item,$key) { return ['id'=>$key,'value'=>$item['name']]; }),
'value'=>$o->recur_schedule ?? '',
])
</div> </div>
</div> </div>
@ -75,12 +41,64 @@
@includeIf('theme.backend.adminlte.service.widget.'.$o->product->category.'.update',['o'=>$o->type]) @includeIf('theme.backend.adminlte.service.widget.'.$o->product->category.'.update',['o'=>$o->type])
<div class="row"> <div class="row">
<div class="col-12"> <div class="col">
@can('wholesaler') @can('wholesaler')
<button type="submit" name="submit" class="btn btn-success mr-0 float-right">@if ($site->exists)Save @else Add @endif</button> <x-leenooks::button.reset/>
<x-leenooks::button.submit class="float-right">Save</x-leenooks::button.submit>
@endcan @endcan
</div> </div>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
@section('page-scripts')
<script type="text/javascript">
function toggle_billing_external(item) {
if (item.is(':checked')) {
$('#suspend_billing').closest('.form-group').addClass('d-none');
$('#invoice_next_at').closest('.form-group').parent().addClass('d-none');
$('#price').closest('.form-group').parent().addClass('d-none');
$('#recur_schedule').closest('.form-group').parent().addClass('d-none');
item.closest('.form-group').addClass('mb-0');
} else {
$('#suspend_billing').closest('.form-group').removeClass('d-none');
$('#invoice_next_at').closest('.form-group').parent().removeClass('d-none');
$('#price').closest('.form-group').parent().removeClass('d-none');
$('#recur_schedule').closest('.form-group').parent().removeClass('d-none');
item.closest('.form-group').removeClass('mb-0');
}
}
function toggle_billing_suspend(item) {
if (item.is(':checked')) {
$('#invoice_next_at').prop('readonly',true);
$('#price').prop('readonly',true);
recur_schedule_readonly(true);
} else {
$('#invoice_next_at').prop('readonly',false);
$('#price').prop('readonly',false);
recur_schedule_readonly(false);
}
}
$(document).ready(function() {
toggle_billing_external($('#external_billing'));
toggle_billing_suspend($('#suspend_billing'));
$('#external_billing').on('click',function(item) {
toggle_billing_external($(this));
});
$('#suspend_billing').on('click',function(item) {
toggle_billing_suspend($(this));
});
});
</script>
@append

View File

@ -1,70 +0,0 @@
<!-- $o=User::class -->
<!-- Suppliers Configuration for this User -->
<div class="row">
<div class="col-6">
<div class="card">
<div class="card-body">
@include('adminlte::widget.success_button')
<table class="table">
<thead>
<tr>
<th>Supplier</th>
<th>ID</th>
<th>Added</th>
</tr>
</thead>
<tbody>
@foreach ($o->suppliers as $so)
<tr>
<td>{{ $so->name }}</td>
<td>{{ $so->pivot->id }}</td>
<td>{{ $so->pivot->created_at }} <a class="float-right" href="{{ url('a/user/supplier/delete',[$o->id,$so->id]) }}"><i class=" fa-fw fas fa-trash"></i></a></td>
</tr>
@endforeach
</tbody>
@if(($x=\App\Models\Supplier::active()->whereNotIn('id',$o->suppliers->pluck('id'))->orderBy('name')->get())->count())
<tfoot>
<tr>
<td colspan="3">
<form class="g-0 needs-validation" method="POST" action="{{ url('a/user/supplier/add',[$o->id]) }}" enctype="multipart/form-data" role="form">
@csrf
<div class="row">
<div class="col-6">
@include('adminlte::widget.form_select',[
'label'=>'Add Supplier',
'icon'=>'fas fa-handshake',
'id'=>'supplier_id',
'old'=>'supplier_id',
'options'=>$x->transform(function($item) { return ['id'=>$item->id,'value'=>$item->name]; }),
'value'=>'',
])
</div>
<div class="col-4">
@include('adminlte::widget.form_text',[
'label'=>'ID',
'icon'=>'fas fa-hashtag',
'id'=>'id',
'old'=>'id',
'name'=>'id',
'value'=>'',
])
</div>
<div class="col-2">
<div class="form-group">
<button type="submit" class="mt-4 float-right btn btn-sm btn-success">Add</button>
</div>
</div>
</div>
</form>
</td>
</tr>
</tfoot>
@endif
</table>
</div>
</div>
</div>
</div>

View File

@ -31,7 +31,7 @@ use App\Models\Supplier;
| |
*/ */
// Default Setup // Global Routes
Auth::routes([ Auth::routes([
'login' => true, 'login' => true,
'logout' => true, 'logout' => true,
@ -40,20 +40,28 @@ Auth::routes([
'confirm' => false, // for additional password confirmations 'confirm' => false, // for additional password confirmations
'verify' => false, // for email verification 'verify' => false, // for email verification
]); ]);
Route::get('logout',[LoginController::class,'logout']) Route::get('logout',[LoginController::class,'logout'])
->name('logout-get'); ->name('logout-get');
Route::redirect('passkey/loggedin','/home'); // Frontend Routes (Non-Authed Users)
Route::view('/','theme.frontend.metronic.welcome.home');
// Logged in users home
Route::redirect('home','u/home');
Route::redirect('passkey/loggedin','u/home');
Route::get('search',[SearchController::class,'search']);
Route::get('pay/paypal/authorise',[PaypalController::class,'authorise']);
Route::get('pay/paypal/cancel',[PaypalController::class,'cancel']);
Route::get('pay/paypal/capture',[PaypalController::class,'capture']);
// Account linking to OPENID host // Account linking to OPENID host
Route::group([],function() { Route::get('auth/{socialProvider}',[SocialLoginController::class,'redirectToProvider']);
Route::get('auth/{socialProvider}',[SocialLoginController::class,'redirectToProvider']); Route::get('auth/{socialProvider}/callback',[SocialLoginController::class,'handleProviderCallback']);
Route::get('auth/{socialProvider}/callback',[SocialLoginController::class,'handleProviderCallback']); Route::get('auth/{socialProvider}/token',[SocialLoginController::class,'handleBearerTokenCallback']);
Route::get('auth/{socialProvider}/token',[SocialLoginController::class,'handleBearerTokenCallback']); Route::get('auth/{socialProvider}/link',[SocialLoginController::class,'link']);
Route::get('auth/{socialProvider}/link',[SocialLoginController::class,'link']); Route::post('auth/{socialProvider}/linkcomplete',[SocialLoginController::class,'linkcomplete']);
Route::post('auth/{socialProvider}/linkcomplete',[SocialLoginController::class,'linkcomplete']);
});
// Return from user switch // Return from user switch
Route::get('admin/switch/stop',[SwitchUserController::class,'switch_stop']) Route::get('admin/switch/stop',[SwitchUserController::class,'switch_stop'])
@ -62,6 +70,13 @@ Route::get('admin/switch/stop',[SwitchUserController::class,'switch_stop'])
// Our Admin Routes - for wholesalers // Our Admin Routes - for wholesalers
Route::group(['middleware'=>['auth','role:wholesaler'],'prefix'=>'a'],function() { Route::group(['middleware'=>['auth','role:wholesaler'],'prefix'=>'a'],function() {
// Linking supplier to account
Route::post('account/supplier/add/{o}',[UserController::class,'supplier_addedit'])
->where('o','[0-9]+');
Route::get('account/supplier/delete/{o}/{so}',[UserController::class,'supplier_delete'])
->where('o','[0-9]+')
->where('so','[0-9]+');
// Site Setup // Site Setup
Route::view('setup','theme.backend.adminlte.a.setup'); Route::view('setup','theme.backend.adminlte.a.setup');
Route::post('setup',[AdminController::class,'setup']); Route::post('setup',[AdminController::class,'setup']);
@ -119,13 +134,6 @@ Route::group(['middleware'=>['auth','role:wholesaler'],'prefix'=>'a'],function()
Route::post('service/update/{o}',[ServiceController::class,'update']) Route::post('service/update/{o}',[ServiceController::class,'update'])
->where('o','[0-9]+'); ->where('o','[0-9]+');
// Linking supplier to user
Route::post('user/supplier/add/{o}',[UserController::class,'supplier_addedit'])
->where('o','[0-9]+');
Route::get('user/supplier/delete/{o}/{so}',[UserController::class,'supplier_delete'])
->where('o','[0-9]+')
->where('so','[0-9]+');
//@deprecated //@deprecated
// Route::get('service/{o}','AdminHomeController@service'); // Route::get('service/{o}','AdminHomeController@service');
// Route::post('service/{o}','AdminHomeController@service_update'); // Route::post('service/{o}','AdminHomeController@service_update');
@ -193,6 +201,7 @@ Route::group(['middleware'=>['auth'],'prefix'=>'u'],function() {
->where('o','[0-9]+') ->where('o','[0-9]+')
->middleware('can:progress,o,status'); ->middleware('can:progress,o,status');
// User settings
Route::view('settings','theme.backend.adminlte.user.settings'); Route::view('settings','theme.backend.adminlte.user.settings');
Route::post('settings/{o}',[UserController::class,'edit']); Route::post('settings/{o}',[UserController::class,'edit']);
}); });
@ -204,20 +213,9 @@ Route::group(['prefix'=>'u'],function() {
->where('code','[0-9A-Z]{6}'); ->where('code','[0-9A-Z]{6}');
}); });
// Frontend Routes (Non-Authed Users) // Frontend
Route::view('/','theme.frontend.metronic.welcome.home'); Route::get('order',[OrderController::class,'index']);
Route::post('order',[OrderController::class,'submit']);
Route::group([],function() {
Route::get('order',[OrderController::class,'index']);
Route::post('order',[OrderController::class,'submit']);
});
Route::get('product_order/{o}',[OrderController::class,'product_order']); Route::get('product_order/{o}',[OrderController::class,'product_order']);
Route::get('product_info/{o}',[OrderController::class,'product_info']); Route::get('product_info/{o}',[OrderController::class,'product_info']);
Route::redirect('home','u/home');
Route::get('search',[SearchController::class,'search']);
Route::get('pay/paypal/authorise',[PaypalController::class,'authorise']);
Route::get('pay/paypal/cancel',[PaypalController::class,'cancel']);
Route::get('pay/paypal/capture',[PaypalController::class,'capture']);