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
9 changed files with 272 additions and 221 deletions

View File

@ -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');
}
}

View File

@ -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',

26
composer.lock generated
View File

@ -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",

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

@ -22,7 +22,7 @@
<div class="card card-light card-tabs">
<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>
@foreach($o->accounts as $ao)
<li class="nav-item">
@ -43,16 +43,16 @@
<div class="card-body">
<div class="tab-content" id="accounts-tab-content">
@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="col-12">
<div class="card-header bg-white">
<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>
@canany('reseller','wholesaler')
<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>
@endcanany
</ul>
@ -60,7 +60,7 @@
<div class="card-body pl-0 pr-0">
<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="col-12 col-xl-7">
@include('theme.backend.adminlte.account.widget.service_active',['o'=>$ao])
@ -73,7 +73,7 @@
</div>
</div>
<div class="tab-pane" id="tab-futureinvoice">
<div class="tab-pane fade" id="tab-futureinvoice">
<div class="row">
<div class="col-12 col-xl-9">
@include('theme.backend.adminlte.invoice.widget.next',['future'=>TRUE])
@ -82,7 +82,7 @@
</div>
@canany('reseller','wholesaler')
<div @class(['tab-pane','active'=>session()->pull('supplier_update')]) id="tab-supplier" role="tabpanel">
<div @class(['tab-pane','fade','show active'=>session()->pull('supplier_update')]) id="tab-supplier">
@include('theme.backend.adminlte.account.widget.supplier',['o'=>$ao])
</div>
@endcanany
@ -95,7 +95,7 @@
@if($o==$user)
@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')
</div>
@endcanany

View File

@ -1,3 +1,5 @@
@use(App\Models\Product)
@extends('adminlte::layouts.app')
@section('htmlheader_title')
@ -26,25 +28,18 @@
<div class="card">
<div class="card-header bg-dark d-flex p-0">
<ul class="nav nav-pills w-100 p-2">
{{--
<li class="nav-item"><a class="nav-link active" href="#product" data-toggle="tab">Product</a></li>
<li class="nav-item"><a class="nav-link" href="#traffic" data-toggle="tab">Traffic</a></li>
--}}
@if (! $o->suspend_billing AND ! $o->external_billing)
<li class="nav-item"><a class="nav-link {{ (! session()->has('service_update')) ? 'active' : '' }}" href="#pending_items" data-toggle="tab">Pending Items</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>
@if ($x=! ($o->suspend_billing || $o->external_billing))
<li class="nav-item"><a @class(['nav-link','active'=>! session()->has('service_update')]) href="#pending_items" data-toggle="tab">Pending Items</a></li>
@endif
@if ($o->product->hasUsage())
<li class="nav-item"><a @class(['nav-link','active'=>! ($x || session()->has('service_update'))]) href="#traffic" data-toggle="tab">Traffic</a></li>
@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')
<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 {{ 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
</ul>
@ -54,58 +49,51 @@
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#">ACTION <span class="caret"></span></a>
<div class="dropdown-menu dropdown-menu-right">
@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>
@endforeach
{{-- <div class="dropdown-divider"></div> --}}
@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>
@endforeach
{{-- <div class="dropdown-divider"></div> --}}
</div>
</li>
</ul>
@endcan
</div><!-- /.card-header -->
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane fade" id="product" role="tabpanel">
Product.
</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">
@if ($x=! ($o->suspend_billing || $o->external_billing))
<div @class(['tab-pane','fade','show active'=>! session()->has('service_update')]) id="pending_items">
@include('theme.backend.adminlte.service.widget.invoice')
</div>
@endif
@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())
@include('theme.backend.adminlte.service.widget.'.$o->product->category.'.usagegraph',['o'=>$o->type])
@endif
</div>
@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')
<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])
</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()))
@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
</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')
</div>
@endcan
</div>
</div>
<!-- /.card -->
</div>
</div>
</div>

View File

@ -1,49 +1,28 @@
<!-- $o=Service\Broadband::class -->
<div class="row">
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
@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 ?? '',
])
<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"/>
</div>
<div class="col-12 col-sm-9 col-md-6 col-xl-7">
@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 ?? '',
])
<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"/>
</div>
</div>
<div class="row">
<div class="col">
Connection Type
<x-leenooks::form.toggle id="pppoe" name="broadband[pppoe]" label="PPPoE" old="broadband.pppoe" :value="$o->pppoe"/>
</div>
</div>
<div class="row">
<div class="col-12 col-sm-9 col-md-12 col-xl-7">
@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 ?? '',
])
<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"/>
</div>
<div class="col-12 col-sm-9 col-md-5 col-xl-5">
@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 ?? '',
])
<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"/>
</div>
</div>
@ -52,25 +31,11 @@
<div class="row">
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
@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') : '',
])
<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')"/>
</div>
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
@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') : ''),
])
<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'))"/>
</div>
</div>
@ -78,26 +43,39 @@
<p class="h6">IP Address</p>
<div class="row">
<div class="col-12 col-lg-5">
@include('adminlte::widget.form_text',[
'label'=>'IPv4 Address',
'icon'=>'fas fa-map-marker',
'id'=>'ipaddress',
'old'=>'broadband.ipaddress',
'name'=>'broadband[ipaddress]',
'value'=>$o->ipaddress ?? '',
])
<x-leenooks::form.text id="ipaddress" name="broadband[ipaddress]" icon="fa-map-marker" label="IPv4 Address" old="broadband.ipaddress" :value="$o->ipaddress"/>
</div>
<div class="col-12 col-lg-7">
<div class="form-group">
@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 ?? '',
])
<x-leenooks::form.text id="ip6address" name="broadband[ip6address]" icon="fa-map-marker-alt" label="IPv6 Address" :value="$o->ip6address"/>
</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="col-12">
<h4>Update Service details</h4>
<form class="g-0 needs-validation" method="POST" action="{{ url('a/service/update',[$o->id]) }}">
@include('adminlte::widget.success')
<h4>Update Service details <x-leenooks::button.success class="float-right"/></h4>
<hr>
<form method="POST" action="{{ url('a/service/update',[$o->id]) }}">
@csrf
<div class="row">
<!-- External Billing -->
<div class="col-2">
@include('adminlte::widget.form_toggle',[
'label'=>'External 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 ?? '',
])
<x-leenooks::form.toggle id="external_billing" name="external_billing" label="External Billing" :value="$o->external_billing"/>
<x-leenooks::form.toggle id="suspend_billing" name="suspend_billing" label="Suspend Billing" :value="$o->suspend_billing"/>
</div>
<div class="col-1"></div>
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
@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') : ''),
])
<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')"/>
</div>
<!-- Price -->
<div class="col-12 col-sm-9 col-md-12 col-xl-3">
@include('adminlte::widget.form_text',[
'label'=>'Price',
'icon'=>'fas fa-dollar-sign',
'id'=>'price',
'old'=>'price',
'name'=>'price',
'value'=>$o->price ?? '',
])
<x-leenooks::form.text name="price" icon="fa-dollar-sign" label="Price" :value="$o->price"/>
</div>
</div>
@ -58,15 +32,7 @@
<div class="col-3"></div>
<div class="col-12 col-sm-9 col-md-6 col-xl-5">
@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 ?? '',
])
<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']])"/>
</div>
</div>
@ -75,12 +41,64 @@
@includeIf('theme.backend.adminlte.service.widget.'.$o->product->category.'.update',['o'=>$o->type])
<div class="row">
<div class="col-12">
<div class="col">
@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
</div>
</div>
</form>
</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

@ -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']);