diff --git a/app/Http/Controllers/ServiceController.php b/app/Http/Controllers/ServiceController.php index 3f89f6f..69ed5c5 100644 --- a/app/Http/Controllers/ServiceController.php +++ b/app/Http/Controllers/ServiceController.php @@ -12,13 +12,14 @@ use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Validator; +use Illuminate\Validation\Rule; use Illuminate\Validation\ValidationException; use Illuminate\View\View; use Symfony\Component\HttpKernel\Exception\HttpException; use App\Http\Requests\ServiceChangeRequest; use App\Mail\{CancelRequest,ChangeRequest}; -use App\Models\{Charge,Product,Service}; +use App\Models\{Charge,Invoice,Product,Service}; class ServiceController extends Controller { @@ -415,39 +416,74 @@ class ServiceController extends Controller */ public function update(Request $request,Service $o) { - if ($o->type->validation()) { - Session::put('service_update',true); - $validator = Validator::make($x=$request->post($o->category),$o->type->validation()); + Session::put('service_update',true); - if ($validator->fails()) { - return redirect() - ->back() - ->withErrors($validator) - ->withInput(); - } + // We dynamically create our validation + $validator = Validator::make( + $request->post(), + $x=collect($o->type->validation()) + ->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)) { - $o->type->forceFill($request->post($o->product->category)); + $validated = collect($validator->validated()); + + // 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(); - if ($request->post('invoice_next_at')) - $o->invoice_next_at = $request->invoice_next_at; + if ($validated->has('invoice_next_at')) + $o->invoice_next_at = $validated->get('invoice_next_at'); - if ($request->post('recur_schedule')) - $o->recur_schedule = $request->recur_schedule; + if ($validated->has('recur_schedule')) + $o->recur_schedule = $validated->get('recur_schedule'); - $o->suspend_billing = ($request->suspend_billing == 'on'); - $o->external_billing = ($request->external_billing == 'on'); - $o->price = $request->price ?: NULL; + $o->suspend_billing = ($validated->get('suspend_billing') == 'on'); + $o->external_billing = ($validated->get('external_billing') == 'on'); + $o->price = $validated->get('price'); // Also update our service start_at date. // @todo We may want to make start_at/stop_at dynamic values calculated by the type records - if ($request->post('start_at')) - $o->start_at = $request->start_at; + if ($validated->has('start_at')) + $o->start_at = $validated->get('start_at'); + else { // For broadband, start_at is connect_at in the type record switch ($o->category) { @@ -459,6 +495,8 @@ class ServiceController extends Controller $o->save(); - return redirect()->back()->with('success','Record Updated'); + return redirect() + ->back() + ->with('success','Record Updated'); } } \ No newline at end of file diff --git a/app/Models/Service/Broadband.php b/app/Models/Service/Broadband.php index 936016a..3874c03 100644 --- a/app/Models/Service/Broadband.php +++ b/app/Models/Service/Broadband.php @@ -88,10 +88,11 @@ class Broadband extends Type implements ServiceUsage public function validation(): array { return [ - 'service_number' => 'nullable|string|min:10|max:10', - 'service_address' => 'nullable|string|min:3', - 'service_username' => 'nullable|string', - 'service_password' => 'nullable|string', + 'service_number' => 'nullable|string|min:10|max:11', + 'service_address' => 'nullable|string|min:5', + 'service_username' => 'exclude_without:pppoe|nullable|string|min:3', + 'service_password' => 'exclude_without:pppoe|nullable|string|min:8', + 'pppoe' => 'nullable|in:on', 'connect_at' => 'nullable|date', 'start_at' => 'nullable|date', 'expire_at' => 'nullable|date|after:start_at', diff --git a/composer.lock b/composer.lock index 61afdf7..4c28a9a 100644 --- a/composer.lock +++ b/composer.lock @@ -1534,16 +1534,16 @@ }, { "name": "laravel/framework", - "version": "v11.16.0", + "version": "v11.17.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "bd4808aaf103ccb5cb4b00bcee46140c070c0ec4" + "reference": "42f505a0c8afc0743f73e70bec08e641e2870bd6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/bd4808aaf103ccb5cb4b00bcee46140c070c0ec4", - "reference": "bd4808aaf103ccb5cb4b00bcee46140c070c0ec4", + "url": "https://api.github.com/repos/laravel/framework/zipball/42f505a0c8afc0743f73e70bec08e641e2870bd6", + "reference": "42f505a0c8afc0743f73e70bec08e641e2870bd6", "shasum": "" }, "require": { @@ -1736,7 +1736,7 @@ "issues": "https://github.com/laravel/framework/issues", "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", @@ -1777,16 +1777,16 @@ }, { "name": "laravel/passport", - "version": "v12.2.0", + "version": "v12.2.1", "source": { "type": "git", "url": "https://github.com/laravel/passport.git", - "reference": "b24c6462835a16163141fbe588533d16603212b7" + "reference": "795bbb406c8f10167df6062032de803bd7d686f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/b24c6462835a16163141fbe588533d16603212b7", - "reference": "b24c6462835a16163141fbe588533d16603212b7", + "url": "https://api.github.com/repos/laravel/passport/zipball/795bbb406c8f10167df6062032de803bd7d686f2", + "reference": "795bbb406c8f10167df6062032de803bd7d686f2", "shasum": "" }, "require": { @@ -1849,7 +1849,7 @@ "issues": "https://github.com/laravel/passport/issues", "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", @@ -3056,11 +3056,11 @@ }, { "name": "leenooks/laravel", - "version": "11.1.2", + "version": "11.1.4", "source": { "type": "git", "url": "https://gitea.dege.au/laravel/leenooks.git", - "reference": "f32c29fa8c4b189add48bde26b7b7115be49355f" + "reference": "f393813311b912f77e4a7082498ed7511482b531" }, "type": "library", "extra": { @@ -3093,7 +3093,7 @@ "laravel", "leenooks" ], - "time": "2024-07-23T08:47:36+00:00" + "time": "2024-07-24T04:08:04+00:00" }, { "name": "leenooks/passkey", diff --git a/database/migrations/2024_07_24_112743_service_broadband_pppoe.php b/database/migrations/2024_07_24_112743_service_broadband_pppoe.php new file mode 100644 index 0000000..cda606a --- /dev/null +++ b/database/migrations/2024_07_24_112743_service_broadband_pppoe.php @@ -0,0 +1,30 @@ +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'); + }); + } +}; diff --git a/resources/views/theme/backend/adminlte/home.blade.php b/resources/views/theme/backend/adminlte/home.blade.php index 52c80ca..85e321d 100644 --- a/resources/views/theme/backend/adminlte/home.blade.php +++ b/resources/views/theme/backend/adminlte/home.blade.php @@ -43,7 +43,7 @@
@foreach($o->accounts as $ao) -
+
! $loop->index]) id="account_{{ $ao->id }}" aria-labelledby="account_{{ $ao->id }}">
@@ -60,7 +60,7 @@
-
! session()->has('supplier_update')]) id="tab-services"> +
! session()->has('supplier_update')]) id="tab-services">
@include('theme.backend.adminlte.account.widget.service_active',['o'=>$ao]) @@ -73,7 +73,7 @@
-
+
@include('theme.backend.adminlte.invoice.widget.next',['future'=>TRUE]) @@ -82,7 +82,7 @@
@canany('reseller','wholesaler') -
session()->pull('supplier_update')]) id="tab-supplier"> +
session()->pull('supplier_update')]) id="tab-supplier"> @include('theme.backend.adminlte.account.widget.supplier',['o'=>$ao])
@endcanany @@ -95,7 +95,7 @@ @if($o==$user) @canany('reseller','wholesaler') -
+
@include('theme.backend.adminlte.widget.admin.reseller')
@endcanany diff --git a/resources/views/theme/backend/adminlte/service/home.blade.php b/resources/views/theme/backend/adminlte/service/home.blade.php index 49ef98e..ad8ed20 100644 --- a/resources/views/theme/backend/adminlte/service/home.blade.php +++ b/resources/views/theme/backend/adminlte/service/home.blade.php @@ -1,3 +1,5 @@ +@use(App\Models\Product) + @extends('adminlte::layouts.app') @section('htmlheader_title') @@ -26,25 +28,18 @@
@@ -54,58 +49,51 @@ ACTION @endcan -
+
-
- Product. -
- @if (! $o->suspend_billing AND ! $o->external_billing) -
+ @if ($x=! ($o->suspend_billing || $o->external_billing)) +
! session()->has('service_update')]) id="pending_items"> @include('theme.backend.adminlte.service.widget.invoice')
@endif + @if ($o->product->hasUsage()) -
+
! ($x || session()->has('service_update'))]) id="traffic"> @if ($o->type->usage(30)->count()) @include('theme.backend.adminlte.service.widget.'.$o->product->category.'.usagegraph',['o'=>$o->type]) @endif
@endif -
- Invoices. -
-
- Email. -
+ @can('wholesaler') -
+
@include('theme.backend.adminlte.service.widget.billinghistory',['o'=>$o])
-
+ +
@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]) @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
-
+
session()->has('service_update')]) id="update"> @include('theme.backend.adminlte.service.widget.update')
@endcan
-
diff --git a/resources/views/theme/backend/adminlte/service/widget/broadband/update.blade.php b/resources/views/theme/backend/adminlte/service/widget/broadband/update.blade.php index f9c3940..7011930 100644 --- a/resources/views/theme/backend/adminlte/service/widget/broadband/update.blade.php +++ b/resources/views/theme/backend/adminlte/service/widget/broadband/update.blade.php @@ -1,49 +1,28 @@
- @include('adminlte::widget.form_text',[ - 'label'=>'Service Number', - 'icon'=>'fas fa-phone', - 'id'=>'service_number', - 'old'=>'broadband.service_number', - 'name'=>'broadband[service_number]', - 'value'=>$o->service_number ?? '', - ]) +
- @include('adminlte::widget.form_text',[ - 'label'=>'Service Address', - 'icon'=>'fas fa-map', - 'id'=>'service_address', - 'old'=>'broadband.service_address', - 'name'=>'broadband[service_address]', - 'value'=>$o->service_address ?? '', - ]) + +
+
+ +
+
+ Connection Type +
- @include('adminlte::widget.form_text',[ - 'label'=>'Service Username', - 'icon'=>'fas fa-user', - 'id'=>'service_username', - 'old'=>'broadband.service_username', - 'name'=>'broadband[service_username]', - 'value'=>$o->service_username ?? '', - ]) +
- @include('adminlte::widget.form_text',[ - 'label'=>'Service Password', - 'icon'=>'fas fa-lock', - 'id'=>'service_password', - 'old'=>'broadband.service_password', - 'name'=>'broadband[service_password]', - 'value'=>$o->service_password ?? '', - ]) +
@@ -52,25 +31,11 @@
- @include('adminlte::widget.form_date',[ - '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') : '', - ]) +
- @include('adminlte::widget.form_date',[ - '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') : ''), - ]) +
@@ -78,26 +43,39 @@

IP Address

- @include('adminlte::widget.form_text',[ - 'label'=>'IPv4 Address', - 'icon'=>'fas fa-map-marker', - 'id'=>'ipaddress', - 'old'=>'broadband.ipaddress', - 'name'=>'broadband[ipaddress]', - 'value'=>$o->ipaddress ?? '', - ]) +
- @include('adminlte::widget.form_text',[ - 'label'=>'IPv6 Address', - 'icon'=>'fas fa-map-marker-alt', - 'id'=>'ip6address', - 'old'=>'broadband.ip6address', - 'name'=>'broadband[ip6address]', - 'value'=>$o->ip6address ?? '', - ]) +
-
\ No newline at end of file +
+ +@section('page-scripts') + +@append \ No newline at end of file diff --git a/resources/views/theme/backend/adminlte/service/widget/update.blade.php b/resources/views/theme/backend/adminlte/service/widget/update.blade.php index 03f3b12..f1aadd1 100644 --- a/resources/views/theme/backend/adminlte/service/widget/update.blade.php +++ b/resources/views/theme/backend/adminlte/service/widget/update.blade.php @@ -1,56 +1,30 @@ + +@use(App\Models\Invoice) +
-

Update Service details

- -
- @include('adminlte::widget.success') +

Update Service details

+
+ @csrf
- @include('adminlte::widget.form_toggle',[ - 'label'=>'External Billing', - 'id'=>'external_billing', - 'old'=>'external_billing', - 'name'=>'external_billing', - 'value'=>$o->external_billing ?? '', - ]) - - - @include('adminlte::widget.form_toggle',[ - 'label'=>'Suspend Billing', - 'id'=>'suspend_billing', - 'old'=>'suspend_billing', - 'name'=>'suspend_billing', - 'value'=>$o->suspend_billing ?? '', - ]) + +
- @include('adminlte::widget.form_date',[ - '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') : ''), - ]) +
- @include('adminlte::widget.form_text',[ - 'label'=>'Price', - 'icon'=>'fas fa-dollar-sign', - 'id'=>'price', - 'old'=>'price', - 'name'=>'price', - 'value'=>$o->price ?? '', - ]) +
@@ -58,15 +32,7 @@
- @include('adminlte::widget.form_select',[ - '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 ?? '', - ]) +
@@ -75,12 +41,64 @@ @includeIf('theme.backend.adminlte.service.widget.'.$o->product->category.'.update',['o'=>$o->type])
-
+
@can('wholesaler') - + + Save @endcan
+ +@section('page-scripts') + +@append \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 48ab86c..5bfc494 100644 --- a/routes/web.php +++ b/routes/web.php @@ -31,7 +31,7 @@ use App\Models\Supplier; | */ -// Default Setup +// Global Routes Auth::routes([ 'login' => true, 'logout' => true, @@ -40,20 +40,28 @@ Auth::routes([ 'confirm' => false, // for additional password confirmations 'verify' => false, // for email verification ]); - Route::get('logout',[LoginController::class,'logout']) ->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 -Route::group([],function() { - 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']); -}); +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']) @@ -193,6 +201,7 @@ Route::group(['middleware'=>['auth'],'prefix'=>'u'],function() { ->where('o','[0-9]+') ->middleware('can:progress,o,status'); + // User settings Route::view('settings','theme.backend.adminlte.user.settings'); Route::post('settings/{o}',[UserController::class,'edit']); }); @@ -204,20 +213,9 @@ Route::group(['prefix'=>'u'],function() { ->where('code','[0-9A-Z]{6}'); }); -// Frontend Routes (Non-Authed Users) -Route::view('/','theme.frontend.metronic.welcome.home'); - -Route::group([],function() { - Route::get('order',[OrderController::class,'index']); - Route::post('order',[OrderController::class,'submit']); -}); +// Frontend +Route::get('order',[OrderController::class,'index']); +Route::post('order',[OrderController::class,'submit']); Route::get('product_order/{o}',[OrderController::class,'product_order']); -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']); +Route::get('product_info/{o}',[OrderController::class,'product_info']); \ No newline at end of file