Move charge to under service
This commit is contained in:
parent
ddd44b643f
commit
743374cb17
@ -30,58 +30,6 @@ class AdminController extends Controller
|
||||
->with('o',$o);
|
||||
}
|
||||
|
||||
// @todo Move to reseller
|
||||
public function charge_addedit(Request $request,Charge $o)
|
||||
{
|
||||
if ($request->post()) {
|
||||
$request->validate([
|
||||
'account_id' => 'required|exists:accounts,id',
|
||||
'charge_at' => 'required|date',
|
||||
'service_id' => 'required|exists:services,id',
|
||||
'quantity' => 'required|numeric|not_in:0',
|
||||
'amount' => 'required|numeric|min:0.01',
|
||||
'sweep_type' => 'required|numeric|in:'.implode(',',array_keys(Charge::sweep)),
|
||||
'type' => 'required|numeric|in:'.implode(',',array_keys(InvoiceItem::type)),
|
||||
'taxable' => 'nullable|boolean',
|
||||
'description' => 'nullable|string|max:128',
|
||||
]);
|
||||
|
||||
if (! $o->exists) {
|
||||
$o->site_id = config('site')->site_id;
|
||||
$o->user_id = Auth::id();
|
||||
$o->active = TRUE;
|
||||
}
|
||||
|
||||
$o->forceFill($request->only(['account_id','charge_at','service_id','quantity','amount','sweep_type','type','taxable','description']));
|
||||
$o->save();
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with('success','Charge recorded: '.$o->id);
|
||||
}
|
||||
|
||||
return view('theme.backend.adminlte.a.charge.addedit')
|
||||
->with('o',$o);
|
||||
}
|
||||
|
||||
// @todo Move to reseller
|
||||
public function charge_pending_account(Request $request,Account $o)
|
||||
{
|
||||
return view('theme.backend.adminlte.a.charge.widgets.pending')
|
||||
->with('list',$o->charges->where('active',TRUE)->where('processed',NULL)->except($request->exclude));
|
||||
}
|
||||
|
||||
/**
|
||||
* List unprocessed charges
|
||||
*
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
*/
|
||||
// @todo Move to reseller
|
||||
public function charge_unprocessed()
|
||||
{
|
||||
return view('theme.backend.adminlte.a.charge.unprocessed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Record payments on an account.
|
||||
*
|
||||
|
@ -8,6 +8,7 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
@ -17,7 +18,7 @@ use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\View\View;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
use App\Http\Requests\ServiceChangeRequest;
|
||||
use App\Http\Requests\{ChargeAdd,ServiceChangeRequest};
|
||||
use App\Mail\{CancelRequest,ChangeRequest};
|
||||
use App\Models\{Charge,Invoice,Product,Service};
|
||||
|
||||
@ -265,6 +266,49 @@ class ServiceController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a charge to a service/account
|
||||
*
|
||||
* @param ChargeAdd $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function charge_addedit(ChargeAdd $request): RedirectResponse
|
||||
{
|
||||
$o = Charge::findOrNew(Arr::get($request->validated(),'id'));
|
||||
|
||||
// Dont update processed charges
|
||||
if ($o->processed)
|
||||
abort(403);
|
||||
|
||||
$o->forceFill(array_merge(Arr::except($request->validated(),['id']),['active'=>TRUE]));
|
||||
$o->save();
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with('success',sprintf('Charge %s #%d',$o->wasRecentlyCreated ? 'Created' : 'Updated',$o->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a charge to a service/account
|
||||
*
|
||||
* @param Request $request
|
||||
* @return View
|
||||
*/
|
||||
public function charge_edit(Request $request): View
|
||||
{
|
||||
$o = Charge::where('processed',FALSE)
|
||||
->where('id',$request->id)
|
||||
->firstOrFail();
|
||||
|
||||
if (Gate::allows('update',$o)) {
|
||||
return view('theme.backend.adminlte.charge.widget.addedit')
|
||||
->with('o',$o)
|
||||
->with('so',$o->service);
|
||||
}
|
||||
|
||||
abort(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all the domains managed by the user
|
||||
*
|
||||
|
46
app/Http/Requests/ChargeAdd.php
Normal file
46
app/Http/Requests/ChargeAdd.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
use App\Models\{Charge,InvoiceItem};
|
||||
|
||||
class ChargeAdd extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Auth::user()
|
||||
->accounts_all
|
||||
->contains(request()->post('account_id'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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('charge_add',true);
|
||||
|
||||
return [
|
||||
'id' => 'sometimes|exists:charges,id',
|
||||
'account_id' => 'required|exists:accounts,id',
|
||||
'charge_at' => 'required|date',
|
||||
'service_id' => 'required|exists:services,id',
|
||||
'site_id' => 'required|exists:sites,id',
|
||||
'quantity' => 'required|numeric|not_in:0',
|
||||
'amount' => 'required|numeric|min:0.01',
|
||||
'sweep_type' => 'required|numeric|in:'.implode(',',array_keys(Charge::sweep)),
|
||||
'type' => 'required|numeric|in:'.implode(',',array_keys(InvoiceItem::type)),
|
||||
'taxable' => 'nullable|boolean',
|
||||
'description' => 'nullable|string|min:5|max:128',
|
||||
];
|
||||
}
|
||||
}
|
@ -4,29 +4,24 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Leenooks\Traits\ScopeActive;
|
||||
|
||||
use App\Casts\CollectionOrNull;
|
||||
use App\Traits\SiteID;
|
||||
|
||||
/**
|
||||
* CLEANUP NOTES:
|
||||
* + Charge Date should not be null
|
||||
* + Attributes should be a collection array
|
||||
* + type should not be null
|
||||
* + It would be useful, given an array of Charges to call a function that renders them into invoice format. This may provide consistence and be the single view of how charges do look on an invoice.
|
||||
*/
|
||||
class Charge extends Model
|
||||
{
|
||||
use SiteID;
|
||||
use ScopeActive;
|
||||
|
||||
protected $casts = [
|
||||
'attributes' => CollectionOrNull::class,
|
||||
];
|
||||
|
||||
protected $dates = [
|
||||
'start_at',
|
||||
'stop_at',
|
||||
'charge_at', // The date the charge applies - since it can be different to created_at
|
||||
'start_at' => 'datetime:Y-m-d',
|
||||
'stop_at' => 'datetime:Y-m-d',
|
||||
'charge_at' => 'datetime:Y-m-d', // The date the charge applies - since it can be different to created_at
|
||||
];
|
||||
|
||||
public const sweep = [
|
||||
@ -61,6 +56,7 @@ class Charge extends Model
|
||||
/** @deprecated use pending */
|
||||
public function scopeUnprocessed($query)
|
||||
{
|
||||
Log::alert('UMO:! Deprecated function scopeUnprocessed()');
|
||||
return $this->scopePending();
|
||||
}
|
||||
|
||||
@ -76,7 +72,21 @@ class Charge extends Model
|
||||
|
||||
public function getNameAttribute()
|
||||
{
|
||||
return sprintf('%s %s',$this->description,$this->getAttribute('attributes') ? join('|',unserialize($this->getAttribute('attributes'))) : '');
|
||||
return sprintf('%s %s',
|
||||
$this->description,
|
||||
$this->getAttribute('attributes')
|
||||
? join('|',unserialize($this->getAttribute('attributes')))
|
||||
: '');
|
||||
}
|
||||
|
||||
public function getSubTotalAttribute(): float
|
||||
{
|
||||
return $this->quantity*$this->amount;
|
||||
}
|
||||
|
||||
public function getTotalAttribute(): float
|
||||
{
|
||||
return $this->account->taxed($this->getSubTotalAttribute());
|
||||
}
|
||||
|
||||
public function getTypeNameAttribute(): string
|
||||
|
41
app/Models/Policies/ChargePolicy.php
Normal file
41
app/Models/Policies/ChargePolicy.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Policies;
|
||||
|
||||
use App\Models\{Account,Charge,User};
|
||||
|
||||
class ChargePolicy
|
||||
{
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function create(User $user,Account $account): bool
|
||||
{
|
||||
return $user->isReseller()
|
||||
&& $user
|
||||
->accounts_all
|
||||
->contains($account->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user,Charge $charge): bool
|
||||
{
|
||||
return $user->isReseller()
|
||||
&& $user
|
||||
->accounts_all
|
||||
->contains($charge->account_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user,Charge $charge): bool
|
||||
{
|
||||
return $user->isReseller()
|
||||
&& $user
|
||||
->accounts_all
|
||||
->contains($charge->account_id);
|
||||
}
|
||||
}
|
28
composer.lock
generated
28
composer.lock
generated
@ -975,16 +975,16 @@
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "7.9.1",
|
||||
"version": "7.9.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "a629e5b69db96eb4939c1b34114130077dd4c6fc"
|
||||
"reference": "d281ed313b989f213357e3be1a179f02196ac99b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/a629e5b69db96eb4939c1b34114130077dd4c6fc",
|
||||
"reference": "a629e5b69db96eb4939c1b34114130077dd4c6fc",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b",
|
||||
"reference": "d281ed313b989f213357e3be1a179f02196ac99b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1081,7 +1081,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/guzzle/issues",
|
||||
"source": "https://github.com/guzzle/guzzle/tree/7.9.1"
|
||||
"source": "https://github.com/guzzle/guzzle/tree/7.9.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1097,7 +1097,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-19T16:19:57+00:00"
|
||||
"time": "2024-07-24T11:22:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
@ -2288,16 +2288,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
"version": "2.5.0",
|
||||
"version": "2.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/commonmark.git",
|
||||
"reference": "0026475f5c9a104410ae824cb5a4d63fa3bdb1df"
|
||||
"reference": "ac815920de0eff6de947eac0a6a94e5ed0fb147c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/0026475f5c9a104410ae824cb5a4d63fa3bdb1df",
|
||||
"reference": "0026475f5c9a104410ae824cb5a4d63fa3bdb1df",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/ac815920de0eff6de947eac0a6a94e5ed0fb147c",
|
||||
"reference": "ac815920de0eff6de947eac0a6a94e5ed0fb147c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2390,7 +2390,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-22T18:18:14+00:00"
|
||||
"time": "2024-07-24T12:52:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/config",
|
||||
@ -3056,11 +3056,11 @@
|
||||
},
|
||||
{
|
||||
"name": "leenooks/laravel",
|
||||
"version": "11.1.4",
|
||||
"version": "11.1.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://gitea.dege.au/laravel/leenooks.git",
|
||||
"reference": "f393813311b912f77e4a7082498ed7511482b531"
|
||||
"reference": "4a4cf3c5bf32f50dcdc8fdc6c3ff680d7f15d90d"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@ -3093,7 +3093,7 @@
|
||||
"laravel",
|
||||
"leenooks"
|
||||
],
|
||||
"time": "2024-07-24T04:08:04+00:00"
|
||||
"time": "2024-07-25T03:52:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "leenooks/passkey",
|
||||
|
@ -22,9 +22,9 @@ return new class extends Migration
|
||||
|
||||
$table->boolean('processed')->default(false);
|
||||
$table->integer('sweep_type')->nullable();
|
||||
$table->integer('type')->nullable();
|
||||
$table->float('amount', 10, 0)->nullable();
|
||||
$table->float('quantity', 10, 0)->nullable();
|
||||
$table->integer('type');
|
||||
$table->float('amount', 10, 0);
|
||||
$table->float('quantity', 10, 0);
|
||||
$table->boolean('taxable')->default(true);
|
||||
$table->jsonb('attributes')->nullable();
|
||||
$table->string('description', 128)->nullable();
|
||||
|
@ -0,0 +1,27 @@
|
||||
<?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
|
||||
{
|
||||
DB::update('ALTER TABLE charges ALTER COLUMN amount SET NOT NULL');
|
||||
DB::update('ALTER TABLE charges ALTER COLUMN quantity SET NOT NULL');
|
||||
DB::update('ALTER TABLE charges ALTER COLUMN type SET NOT NULL');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
DB::update('ALTER TABLE charges ALTER COLUMN amount SET DEFAULT NULL');
|
||||
DB::update('ALTER TABLE charges ALTER COLUMN quantity SET DEFAULT NULL');
|
||||
DB::update('ALTER TABLE charges ALTER COLUMN type SET DEFAULT NULL'); }
|
||||
};
|
@ -1,350 +0,0 @@
|
||||
@extends('adminlte::layouts.app')
|
||||
|
||||
@section('htmlheader_title')
|
||||
Charge {{ $o->id ? '#'. $o->id : '' }}
|
||||
@endsection
|
||||
@section('page_title')
|
||||
Charge
|
||||
@endsection
|
||||
|
||||
@section('contentheader_title')
|
||||
Record Charge
|
||||
@endsection
|
||||
@section('contentheader_description')
|
||||
@endsection
|
||||
|
||||
@section('main-content')
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h1 class="card-title">Record Charge {{ $o->id ? '#'. $o->id : '' }}</h1>
|
||||
@if(session()->has('success'))
|
||||
<span class="ml-3 pt-0 pb-0 pr-1 pl-1 btn btn-outline-success"><small>{{ session()->get('success') }}</small></span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form class="g-0 needs-validation" method="POST" role="form">
|
||||
@csrf
|
||||
|
||||
<div class="row">
|
||||
<!-- DATE CHARGE -->
|
||||
<div class="col-4">
|
||||
<div class="form-group has-validation">
|
||||
<label for="charge_at">Date Charge</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-calendar"></i></span>
|
||||
</div>
|
||||
<input type="date" class="form-control @error('charge_at') is-invalid @enderror" id="charge_at" name="charge_at" value="{{ old('charge_at',($o->exists ? $o->charge_at : \Carbon\Carbon::now())->format('Y-m-d')) }}" required>
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('charge_at')
|
||||
{{ $message }}
|
||||
@else
|
||||
Charge Date is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Date of Charge</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- QUANTITY -->
|
||||
<div class="offset-6 col-2">
|
||||
<div class="form-group has-validation">
|
||||
<label class="float-right" for="quantity">Quantity</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-hashtag"></i></span>
|
||||
</div>
|
||||
<input type="text" class="text-right form-control @error('quantity') is-invalid @enderror" id="quantity" name="quantity" value="{{ old('quantity',$o->exists ? $o->quantity : 1) }}" required>
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('quantity')
|
||||
{{ $message }}
|
||||
@else
|
||||
Quantity is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- ACCOUNTS -->
|
||||
<div class="col-4">
|
||||
<div class="form-group has-validation">
|
||||
<label for="account_id">Account</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-user"></i></span>
|
||||
</div>
|
||||
<select class="form-control @error('account_id') is-invalid @enderror" id="account_id" name="account_id" required>
|
||||
<option value=""></option>
|
||||
@foreach (\App\Models\Account::active()->with(['user'])->get()->sortBy('name') as $ao)
|
||||
<option value="{{ $ao->id }}" {{ $ao->id == old('account_id',$o->exists ? $o->account_id : NULL) ? 'selected' : '' }}>{{ $ao->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('account_id')
|
||||
{{ $message }}
|
||||
@else
|
||||
Account is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Account to add charge to.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SWEEP TYPE -->
|
||||
<div class="offset-1 col-4">
|
||||
<div class="form-group has-validation">
|
||||
<label for="sweep_type">Sweep</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-dollar-sign"></i></span>
|
||||
</div>
|
||||
<select class="form-control @error('sweep_type') is-invalid @enderror" id="sweep_type" name="sweep_type" required>
|
||||
@foreach (\App\Models\Charge::sweep as $k=>$v)
|
||||
<option value="{{ $k }}" {{ $k == old('sweep_type',$o->exists ? $o->sweep_type : NULL) ? 'selected' : '' }}>{{ $v }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('sweep_type')
|
||||
{{ $message }}
|
||||
@else
|
||||
Sweep Type is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">When to add the charge to an invoice.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TAXABLE -->
|
||||
<div class="col-1">
|
||||
<div class="form-check has-validation">
|
||||
<label for="taxable">Taxable</label>
|
||||
<div class="form-check text-right">
|
||||
<input type="checkbox" class="form-check-input @error('taxable') is-invalid @enderror" id="taxable" name="taxable" value="1" {{ old('taxable',$o->exists ? $o->taxable : 1) ? 'checked' : '' }}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMOUNT -->
|
||||
<div class="col-2">
|
||||
<div class="form-group has-validation">
|
||||
<label class="float-right" for="amount">Amount</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-dollar-sign"></i></span>
|
||||
</div>
|
||||
<input type="text" class="text-right form-control @error('amount') is-invalid @enderror" id="amount" name="amount" value="{{ number_format(old('amount',$o->exists ? $o->amount : 0),2) }}">
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('amount')
|
||||
{{ $message }}
|
||||
@else
|
||||
Amount is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Amount (ex Tax).</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- SERVICES -->
|
||||
<div class="col-4">
|
||||
<div class="form-group has-validation">
|
||||
<label for="service_id">Services</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-bolt"></i></span>
|
||||
</div>
|
||||
<select class="form-control @error('service_id') is-invalid @enderror" id="service_id" name="service_id" required>
|
||||
</select>
|
||||
<span class="ml-2 pt-2"><i class="fas fa-spinner d-none"></i></span>
|
||||
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('service_id')
|
||||
{{ $message }}
|
||||
@else
|
||||
Service is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
{{--
|
||||
<!-- @todo -->
|
||||
<span class="input-helper"><sup>**</sup>Service inactive.</span>
|
||||
--}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CHARGE TYPE -->
|
||||
<div class="offset-1 col-4">
|
||||
<div class="form-group has-validation">
|
||||
<label for="type">Type</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-dollar-sign"></i></span>
|
||||
</div>
|
||||
<select class="form-control @error('type') is-invalid @enderror" id="type" name="type" required>
|
||||
@foreach (collect(\App\Models\InvoiceItem::type)->sort() as $k=>$v)
|
||||
<option value="{{ $k }}" {{ $k == old('type',$o->exists ? $o->type : NULL) ? 'selected' : '' }}>{{ $v }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('type')
|
||||
{{ $message }}
|
||||
@else
|
||||
Type is required.
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-helper">Charge type.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TOTAL -->
|
||||
<div class="offset-1 col-2">
|
||||
<label class="float-right" for="fees_amt">Total</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-dollar-sign"></i></span>
|
||||
</div>
|
||||
<input type="text" class="text-right form-control" id="total" value="{{ number_format($o->exists ? $o->quantity*$o->amount : 0,2) }}" disabled>
|
||||
</div>
|
||||
<span class="input-helper">Total (ex Tax).</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- DESCRIPTION -->
|
||||
<div class="col-12">
|
||||
<div class="form-group has-validation">
|
||||
<label for="description">Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-file-alt"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control @error('description') is-invalid @enderror" id="description" name="description" value="{{ old('description',$o->exists ? $o->description : '') }}">
|
||||
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('description')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<a href="{{ url('/home') }}" class="btn btn-danger">Cancel</a>
|
||||
@can('wholesaler')
|
||||
<button type="submit" name="submit" class="btn btn-success mr-0 float-right">@if ($site->exists)Save @else Add @endif</button>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-5">
|
||||
<div id="pending"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('page-scripts')
|
||||
@css(select2)
|
||||
@js(select2,autofocus)
|
||||
|
||||
<script type="text/javascript">
|
||||
function populate(account,spinner) {
|
||||
spinner.toggleClass('d-none').toggleClass('fa-spin');
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
url: '{{ url('api/r/services') }}'+'/'+account,
|
||||
data: {include: {{ $o->service_id ?: 'null' }} },
|
||||
timeout: 2000,
|
||||
error: function(x) {
|
||||
spinner.toggleClass('d-none').toggleClass('fa-spin');
|
||||
alert('Failed to submit');
|
||||
},
|
||||
success: function(data) {
|
||||
$("select[name=service_id]").empty();
|
||||
$.each(data,function(i,j) {
|
||||
var row = '<option value="' + j.id + '" '+(j.id == {{ $o->service_id ?: 'null' }} ? 'selected' : '')+'>' + j.id + ': ' + j.category_name + ' ' + j.name_short + ((! j.active) ? ' **' : '') +'</option>';
|
||||
$(row).appendTo("select[name=service_id]");
|
||||
});
|
||||
|
||||
spinner.toggleClass('d-none').toggleClass('fa-spin');
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
dataType: 'html',
|
||||
data: {exclude: {{ $o->id ?: 'null' }}},
|
||||
cache: false,
|
||||
url: '{{ url('r/charges') }}'+'/'+account,
|
||||
timeout: 2000,
|
||||
error: function(x) {
|
||||
spinner.toggleClass('d-none').toggleClass('fa-spin');
|
||||
alert('Failed to submit');
|
||||
},
|
||||
success: function(data) {
|
||||
$("div[id=pending]").empty().append(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function total() {
|
||||
$('#total').val(($('#quantity').val()*$('#amount').val()).toFixed(2));
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var spinner = $('#service_id').parent().find('i.fas.fa-spinner');
|
||||
|
||||
if ($('#account_id').val()) {
|
||||
populate($('#account_id').val(),spinner);
|
||||
}
|
||||
|
||||
$('#account_id').select2({
|
||||
sorter: data => data.sort((a, b) => a.text.localeCompare(b.text)),
|
||||
})
|
||||
.on('change',function(e) {
|
||||
$("select[id=service_id]").empty();
|
||||
|
||||
if (! $(this).val()) {
|
||||
return;
|
||||
}
|
||||
|
||||
populate($(this).val(),spinner);
|
||||
});
|
||||
|
||||
$('#service_id').select2();
|
||||
|
||||
$('#sweep_type').select2();
|
||||
|
||||
$('#type').select2();
|
||||
|
||||
if ($('#quantity').val() && $('#amount').val()) {
|
||||
total();
|
||||
}
|
||||
|
||||
$('#quantity').on('change',total);
|
||||
$('#amount').on('change',total);
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -1,3 +1,5 @@
|
||||
@use(App\Models\Charge)
|
||||
|
||||
@extends('adminlte::layouts.app')
|
||||
|
||||
@section('htmlheader_title')
|
||||
@ -32,17 +34,21 @@
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach(\App\Models\Charge::unprocessed()->with(['account.user','service'])->get() as $o)
|
||||
@forelse(Charge::pending()->with(['account.user','service'])->get() as $o)
|
||||
<tr>
|
||||
<td><a href="{{ url('a/charge/addedit',$o->id) }}">{{ $o->id }}</a></td>
|
||||
<td>{{ $o->id }}</td>
|
||||
<td>{{ $o->charge_at->format('Y-m-d') }}</td>
|
||||
<td>{{ $o->created_at->format('Y-m-d') }}</td>
|
||||
<td>{{ $o->account->name }}</td>
|
||||
<td>{{ $o->service->name_short }}</td>
|
||||
<td><a href="{{ url('u/service',$o->service_id) }}">{{ $o->service->name_short }}</a></td>
|
||||
<td>{{ $o->description }}</td>
|
||||
<td class="text-right">{{ number_format($o->quantity*$o->amount,2) }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7">Not charges unprocessed</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
@ -0,0 +1,107 @@
|
||||
<!-- $o=Charge::class -->
|
||||
@use(Carbon\Carbon)
|
||||
@use(App\Models\Charge)
|
||||
@use(App\Models\InvoiceItem)
|
||||
|
||||
<form method="POST" action="{{ url('r/charge/addedit') }}">
|
||||
@csrf
|
||||
<input type="hidden" name="account_id" value="{{ old('account_id',$so->account_id) }}">
|
||||
<input type="hidden" name="service_id" value="{{ old('service_id',$so->id) }}">
|
||||
<input type="hidden" name="site_id" value="{{ old('site_id',$so->site_id) }}">
|
||||
@if($id=old('id',isset($o) ? $o->id : FALSE))
|
||||
<input type="hidden" name="id" value="{{ $id }}">
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h3>Charge @if($id)Update #{{ $id }}@else Add @endif
|
||||
<x-leenooks::button.success class="float-right"/>
|
||||
@error('id')
|
||||
<x-leenooks::button.error class="float-right" name="id"/>
|
||||
@enderror
|
||||
</h3>
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="row">
|
||||
<!-- DATE CHARGE -->
|
||||
<div class="col-12 col-lg-10">
|
||||
<x-leenooks::form.date name="charge_at" icon="fa-calendar" label="Date Charge" feedback="Charge Date is required" :value="($o->charge_at ?? Carbon::now())->format('Y-m-d')"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- SWEEP TYPE -->
|
||||
<div class="col-12 col-lg-10">
|
||||
<x-leenooks::form.select name="sweep_type" icon="fa-clock" label="Sweep" feedback="Sweep Type is required" helper="When to add the charge to an invoice." :options="collect(Charge::sweep)->map(fn($item,$key)=>['id'=>$key,'value'=>$item])" :value="$o->sweep_type ?? NULL"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- CHARGE TYPE -->
|
||||
<div class="col-12 col-lg-10">
|
||||
<x-leenooks::form.select name="type" icon="fa-archive" label="Type" feedback="Charge Type is required" helper="Charge Type." :options="collect(InvoiceItem::type)->sort()->map(fn($item,$key)=>['id'=>$key,'value'=>$item])" :value="$o->type ?? NULL"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="row">
|
||||
<!-- QUANTITY -->
|
||||
<div class="col-12 offset-lg-6 col-lg-6">
|
||||
<x-leenooks::form.text class="float-right text-right" id="quantity" name="quantity" icon="fa-hashtag" label="Quantity" feedback="Quantity is required" :value="$o->quantity ?? 1"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- TAXABLE -->
|
||||
<div class="col-1 offset-lg-3 col-lg-1">
|
||||
<x-leenooks::form.checkbox name="taxable" label="Taxable" value="1" checked/>
|
||||
</div>
|
||||
|
||||
<!-- AMOUNT -->
|
||||
<div class="col-11 col-lg-8">
|
||||
<x-leenooks::form.text class="float-right text-right" id="amount" name="amount" icon="fa-dollar-sign" label="Amount" feedback="Amount is required" helper="Amount (ex Tax)." :value="$o->amount ?? 0.00"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- TOTAL -->
|
||||
<div class="col-12 offset-lg-4 col-lg-8">
|
||||
<x-leenooks::form.text class="float-right text-right" id="total" name="total" icon="fa-dollar-sign" label="Total" helper="Total (ex Tax)." :value="$o->subtotal ?? 0.00" disabled/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- DESCRIPTION -->
|
||||
<div class="col">
|
||||
<x-leenooks::form.text name="description" icon="fa-file-alt" label="Description" helper="Description for Invoice" :value="$o->description ?? NULL"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<x-leenooks::button.reset/>
|
||||
<x-leenooks::button.submit class="float-right">@if($id)Update @else Add @endif</x-leenooks::button.submit>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@section('page-scripts')
|
||||
<script type="text/javascript">
|
||||
function total() {
|
||||
$('#total').val(($('#quantity').val()*$('#amount').val()).toFixed(2));
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$(document).on('change','#quantity',function() { total(); });
|
||||
$(document).on('change','#amount',function() { total(); });
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -29,17 +29,20 @@
|
||||
<div class="card-header bg-dark d-flex p-0">
|
||||
<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'=>! session()->has('service_update')]) href="#pending_items" data-toggle="tab">Pending Items</a></li>
|
||||
<li class="nav-item"><a @class(['nav-link','active'=>! (session()->has('service_update') || session()->has('charge_add'))]) 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>
|
||||
<li class="nav-item"><a @class(['nav-link','active'=>! ($x || (session()->has('service_update') || session()->has('charge_add')))]) href="#traffic" data-toggle="tab">Traffic</a></li>
|
||||
@endif
|
||||
|
||||
@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','active'=>session()->has('service_update')]) href="#update" data-toggle="tab">Update</a></li>
|
||||
@if($o->active || $o->isPending())
|
||||
<li class="nav-item"><a @class(['nav-link','active'=>session()->has('charge_add')]) href="#charge" data-toggle="tab">Charge</a></li>
|
||||
@endif
|
||||
@endcan
|
||||
</ul>
|
||||
|
||||
@ -59,16 +62,16 @@
|
||||
@endcan
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="card-body pt-2 pl-2 pr-2 pb-0">
|
||||
<div class="tab-content">
|
||||
@if($x=! ($o->suspend_billing || $o->external_billing))
|
||||
<div @class(['tab-pane','fade','show active'=>! session()->has('service_update')]) id="pending_items">
|
||||
<div @class(['tab-pane','fade','show active'=>! (session()->has('service_update') || session()->has('charge_add'))]) id="pending_items">
|
||||
@include('theme.backend.adminlte.service.widget.invoice')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($o->product->hasUsage())
|
||||
<div @class(['tab-pane','fade','show active'=>! ($x || session()->has('service_update'))]) id="traffic">
|
||||
<div @class(['tab-pane','fade','show active'=>! ($x || (session()->has('service_update') || session()->has('charge_add')))]) id="traffic">
|
||||
@if($o->type->usage(30)->count())
|
||||
@include('theme.backend.adminlte.service.widget.'.$o->product->category.'.usagegraph',['o'=>$o->type])
|
||||
@endif
|
||||
@ -88,9 +91,15 @@
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div @class(['tab-pane','fade','show active'=>session()->pull('service_update')]) id="update">
|
||||
<div @class(['tab-pane','fade','show active'=>session()->pull('service_update'),'p-2']) id="update">
|
||||
@include('theme.backend.adminlte.service.widget.update')
|
||||
</div>
|
||||
|
||||
@if($o->active || $o->isPending())
|
||||
<div @class(['tab-pane','fade','show active'=>session()->pull('charge_add')]) id="charge">
|
||||
@include('theme.backend.adminlte.service.widget.charge')
|
||||
</div>
|
||||
@endif
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
|
@ -0,0 +1,102 @@
|
||||
@use(App\Models\Charge)
|
||||
|
||||
<div class="card card-secondary card-outline card-outline-tabs">
|
||||
<div class="card-header p-0 border-bottom-0">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item"><a class="nav-link active" href="#charge_add" data-toggle="tab">Charge</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#charge_pending" data-toggle="tab">Pending</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="charge_add">
|
||||
@include('theme.backend.adminlte.charge.widget.addedit',['o'=>NULL,'so'=>$o])
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="charge_pending">
|
||||
<table class="table table-sm" id="svc_bill_hist">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Created</th>
|
||||
<th>Charge</th>
|
||||
<th>Type</th>
|
||||
<th class="text-right">Q</th>
|
||||
<th class="text-right">Total</th>
|
||||
<th>Processed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@forelse(Charge::where('service_id',$o->id)->active()->orderBy('charge_at','DESC')->with(['account'])->get() as $oo)
|
||||
<tr>
|
||||
<td>{{ $oo->id }}</td>
|
||||
<td>{{ $oo->created_at->format('Y-m-d') }}</td>
|
||||
<td>{{ $oo->charge_at?->format('Y-m-d') }}</td>
|
||||
<td>{{ $oo->type_name }}</td>
|
||||
<td class="text-right">{{ number_format($oo->quantity) }}</td>
|
||||
<td class="text-right">{{ number_format($oo->total,2) }}</td>
|
||||
<td>
|
||||
{{ $oo->processed ? 'YES' : 'NO' }}
|
||||
@if(! $oo->processed)
|
||||
<span class="float-right">
|
||||
<a class="charge_edit" id="{{ $oo->id }}" href="#"><i class="fas fa-fw fa-edit"></i></a>
|
||||
<a class="charge_delete" id="{{ $oo->id }}" href="#"><i class="fas fa-fw fa-trash"></i></a>
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7">No Charges for this Service</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<x-leenooks::modal.delete trigger="charge_delete"/>
|
||||
|
||||
@section('page-scripts')
|
||||
<script type="text/javascript">
|
||||
function total() {
|
||||
$('#total').val(($('#quantity').val()*$('#amount').val()).toFixed(2));
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var loaded = [];
|
||||
|
||||
$('.charge_edit').on('click',function(item) {
|
||||
// Open our charge add tab automatically
|
||||
$('.nav-item a[href="#charge_add"]').tab('show');
|
||||
|
||||
if (loaded[item.currentTarget.id])
|
||||
return false;
|
||||
|
||||
console.log(item.currentTarget.id);
|
||||
// Prepopulate with the details of the charge
|
||||
$.ajax({
|
||||
url: '{{ url('r/charge/edit') }}',
|
||||
method: 'POST',
|
||||
data: { id: item.currentTarget.id },
|
||||
dataType: 'html',
|
||||
|
||||
}).done(function(html) {
|
||||
$('div[id="charge_add"]').empty().append(html);
|
||||
loaded[item.currentTarget.id] = true;
|
||||
|
||||
}).fail(function() {
|
||||
alert('Failed');
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
//<a href="{{ url('/api/charge/delete',$o->id) }}">
|
||||
</script>
|
||||
@append
|
@ -6,5 +6,5 @@
|
||||
</div>
|
||||
|
||||
<!-- Default to the left -->
|
||||
<strong>© {{ \Carbon\Carbon::now()->year }} <a href="#">Leenooks</a>.</strong> All rights reserved. [#{{ $site->site_id }}]
|
||||
<strong>© {{ \Carbon\Carbon::now()->year }} <a href="#">Leenooks</a>.</strong> All rights reserved. @isset($site)[#{{ $site->site_id }}]@endisset
|
||||
</footer>
|
@ -1,21 +1,21 @@
|
||||
<li class="nav-header">MAIN</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('home') }}" class="nav-link @if(preg_match('#^u/home$#',$path=request()->path())) active @endif">
|
||||
<a href="{{ url('home') }}" @class(['nav-link','active'=>($path=request()->path()) === 'u/home'])>
|
||||
<i class="nav-icon fas fa-home"></i> <p>Home</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- ORDERS -->
|
||||
<li class="nav-item has-treeview @if(preg_match('#^order#',$path)) menu-open @endif">
|
||||
<a href="#" class="nav-link @if(preg_match('#^order#',$path)) active @endif">
|
||||
<li @class(['nav-item','has-treeview','menu-open'=>$x=preg_match('#^order#',$path),'menu-closed'=>! $x])>
|
||||
<a href="#" @class(['nav-link','active'=>$path === 'order'])>
|
||||
<i class="nav-icon fas fa-cash-register"></i>
|
||||
<p>Orders <i class="fas fa-angle-left right"></i></p>
|
||||
</a>
|
||||
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('order') }}" class="nav-link @if(preg_match('#^order$#',$path)) active @endif">
|
||||
<a href="{{ url('order') }}" @class(['nav-link','active'=>$path === 'order'])>
|
||||
<i class="fas fa-tag nav-icon"></i> <p>New Order</p>
|
||||
</a>
|
||||
</li>
|
||||
@ -23,44 +23,22 @@
|
||||
</li>
|
||||
|
||||
@can('wholesaler')
|
||||
<!-- CHARGES -->
|
||||
<li class="nav-item has-treeview @if(preg_match('#^a/charge/#',$path)) menu-open @endif">
|
||||
<a href="#" class="nav-link @if(preg_match('#^a/charge/#',$path)) active @endif">
|
||||
<i class="nav-icon fas fa-plus"></i>
|
||||
<p>Charges <i class="fas fa-angle-left right"></i></p>
|
||||
</a>
|
||||
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/charge/addedit') }}" class="nav-link @if(request()->path() == 'a/charge/addedit') active @endif">
|
||||
<i class="fas fa-cart-plus nav-icon"></i> <p>New Charge</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/charge/unprocessed') }}" class="nav-link @if(request()->path() == 'a/charge/unprocessed') active @endif">
|
||||
<i class="fas fa-list nav-icon"></i> <p>Unprocessed</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<!-- PAYMENTS -->
|
||||
<li class="nav-item has-treeview @if(preg_match('#^a/payment/#',$path)) menu-open @endif">
|
||||
<a href="#" class="nav-link @if(preg_match('#^a/payment/#',$path)) active @endif">
|
||||
<li @class(['nav-item','has-treeview','menu-open'=>$x=preg_match('#^a/payment/#',$path),'menu-closed'=>! $x])>
|
||||
<a href="#" @class(['nav-link','active'=>preg_match('#^a/payment/#',$path)])>
|
||||
<i class="nav-icon fas fa-receipt"></i>
|
||||
<p>Payments <i class="fas fa-angle-left right"></i></p>
|
||||
</a>
|
||||
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/payment/addedit') }}" class="nav-link @if(preg_match('#^a/payment/addedit#',$path)) active @endif">
|
||||
<a href="{{ url('a/payment/addedit') }}" @class(['nav-link','active'=>$path === 'a/payment/addedit'])>
|
||||
<i class="fas fa-money-bill nav-icon"></i> <p>New Payment</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/payment/unapplied') }}" class="nav-link @if(preg_match('#^a/payment/unapplied$#',$path)) active @endif">
|
||||
<a href="{{ url('a/payment/unapplied') }}" @class(['nav-link','active'=>$path === 'a/payment/unapplied'])>
|
||||
<i class="fas fa-receipt nav-icon"></i> <p>Unapplied</p>
|
||||
</a>
|
||||
</li>
|
||||
@ -72,61 +50,61 @@
|
||||
<li class="nav-header">ADMIN</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('auth/intuit') }}" class="nav-link @if(preg_match('#^auth/intuit#',$path)) active @endif">
|
||||
<a href="{{ url('auth/intuit') }}" @class(['nav-link','active'=>preg_match('#^auth/intuit#',$path)])>
|
||||
<i class="nav-icon fas fa-calculator"></i> <p>Quickbooks Link</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/setup') }}" class="nav-link @if(preg_match('#^a/setup#',$path)) active @endif">
|
||||
<a href="{{ url('a/setup') }}" @class(['nav-link','active'=>preg_match('#^a/setup#',$path)])>
|
||||
<i class="nav-icon fas fa-cogs"></i> <p>Site Setup</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- CHECKOUT (PAYMENTS) -->
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/checkout') }}" class="nav-link @if(preg_match('#^a/checkout#',$path)) active @endif">
|
||||
<a href="{{ url('a/checkout') }}" @class(['nav-link','active'=>preg_match('#^a/checkout#',$path)])>
|
||||
<i class="nav-icon fas fa-money-check-alt"></i> <p>Payments</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- PRODUCTS -->
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/product') }}" class="nav-link @if(preg_match('#^a/product#',$path)) active @endif">
|
||||
<a href="{{ url('a/product') }}" @class(['nav-link','active'=>preg_match('#^a/product#',$path)])>
|
||||
<i class="nav-icon fas fa-barcode"></i> <p>Products</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- SUPPLIERS -->
|
||||
<li class="nav-item has-treeview @if(preg_match('#^a/supplier#',$path)) menu-open @endif">
|
||||
<a href="#" class="nav-link @if(preg_match('#^a/supplier#',$path)) active @endif">
|
||||
<li @class(['nav-item','has-treeview','menu-open'=>$x=preg_match('#^a/supplier#',$path),'menu-closed'=>! $x])>
|
||||
<a href="#" @class(['nav-link','active'=>preg_match('#^a/supplier#',$path)])>
|
||||
<i class="nav-icon fas fa-user-tag"></i>
|
||||
<p>Suppliers <i class="fas fa-angle-left right"></i></p>
|
||||
</a>
|
||||
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/supplier') }}" class="nav-link @if(preg_match('#^a/supplier(/[cost|details]+/[0-9]+)?$#',$path)) active @endif">
|
||||
<a href="{{ url('a/supplier') }}" @class(['nav-link','active'=>preg_match('#^a/supplier(/[cost|details]+/[0-9]+)?$#',$path)])>
|
||||
<i class="nav-icon fas fa-cogs"></i> <p>Configuration</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/supplier/product/add') }}" class="nav-link @if(preg_match('#^a/supplier/product/(add|edit)#',$path)) active @endif">
|
||||
<a href="{{ url('a/supplier/product/add') }}" @class(['nav-link','active'=>preg_match('#^a/supplier/product/(add|edit)#',$path)])>
|
||||
<i class="nav-icon fas fa-barcode"></i> <p>New Product</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item has-treeview @if(preg_match('#^a/report/(accounts|products|services)#',$path))menu-open @else menu-closed @endif">
|
||||
<a href="#" class="nav-link @if(preg_match('#^a/report/(accounts|products|services)#',$path)) active @endif">
|
||||
<li @class(['nav-item','has-treeview','menu-open'=>$x=preg_match('#^a/report/(accounts|products|services)#',$path),'menu-closed'=>! $x])>
|
||||
<a href="#" @class(['nav-link','active'=>preg_match('#^a/report/(accounts|products|services)#',$path)])>
|
||||
<i class="nav-icon fas fa-list"></i> <p>REPORT<i class="fas fa-angle-left right"></i></p>
|
||||
</a>
|
||||
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/report/accounts') }}" class="nav-link @if(preg_match('#^a/report/accounts#',$path))active @endif">
|
||||
<a href="{{ url('a/report/accounts') }}" @class(['nav-link','active'=>$path === 'a/report/accounts'])>
|
||||
<i class="nav-icon fas fa-users"></i> <p>Accounts</p>
|
||||
</a>
|
||||
</li>
|
||||
@ -134,7 +112,7 @@
|
||||
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/report/products') }}" class="nav-link @if(preg_match('#^a/report/products#',$path))active @endif">
|
||||
<a href="{{ url('a/report/products') }}" @class(['nav-link','active'=>$path === 'a/report/products'])>
|
||||
<i class="nav-icon fas fa-barcode"></i> <p>Products</p>
|
||||
</a>
|
||||
</li>
|
||||
@ -142,7 +120,7 @@
|
||||
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('a/report/services') }}" class="nav-link @if(preg_match('#^a/report/services#',$path))active @endif">
|
||||
<a href="{{ url('a/report/services') }}" @class(['nav-link','active'=>$path === 'a/report/services'])>
|
||||
<i class="nav-icon fas fa-layer-group"></i> <p>Services</p>
|
||||
</a>
|
||||
</li>
|
||||
@ -153,26 +131,32 @@
|
||||
@can('reseller')
|
||||
<li class="nav-header">RESELLER</li>
|
||||
|
||||
<li class="nav-item has-treeview @if(preg_match('#^r/report/(domain|email|hosting)#',$path))menu-open @else menu-closed @endif">
|
||||
<a href="#" class="nav-link @if(preg_match('#^r/report/(domain|email|hosting)#',$path)) active @endif">
|
||||
<li @class(['nav-item','has-treeview','menu-open'=>$x=preg_match('#^r/report/(charge|domain|email|hosting)#',$path),'menu-closed'=>! $x])>
|
||||
<a href="#" @class(['nav-link','active'=>preg_match('#^r/report/(charge|domain|email|hosting)#',$path)])>
|
||||
<i class="nav-icon fas fa-list"></i> <p>REPORT<i class="fas fa-angle-left right"></i></p>
|
||||
</a>
|
||||
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('r/report/domain') }}" class="nav-link @if(preg_match('#^r/report/domain$#',$path))active @endif">
|
||||
<a href="{{ url('r/report/charge/pending') }}" @class(['nav-link','active'=>$path === 'r/report/charge/pending'])>
|
||||
<i class="nav-icon fas fa-list"></i> <p>Charges Unprocessed</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('r/report/domain') }}" @class(['nav-link','active'=>$path === 'r/report/domain'])>
|
||||
<i class="nav-icon fas fa-globe-asia"></i> <p>Domain Names</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('r/report/email') }}" class="nav-link @if(preg_match('#^r/report/email$#',$path))active @endif">
|
||||
<a href="{{ url('r/report/email') }}" @class(['nav-link','active'=>$path === 'r/report/email'])>
|
||||
<i class="nav-icon fas fa-envelope"></i> <p>Email Hosting</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{{ url('r/report/hosting') }}" class="nav-link @if(preg_match('#^r/report/hosting$#',$path))active @endif">
|
||||
<a href="{{ url('r/report/hosting') }}" @class(['nav-link','active'=>$path === 'r/report/hosting'])>
|
||||
<i class="nav-icon fas fa-sitemap"></i> <p>Web Hosting</p>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -26,8 +26,6 @@ Route::group(['middleware'=>['auth:api','role:wholesaler']], function() {
|
||||
|
||||
// Reseller API calls
|
||||
Route::group(['middleware'=>['auth:api','role:reseller']], function() {
|
||||
Route::get('/r/services/{o}',[ResellerServicesController::class,'services'])
|
||||
->where('o','[0-9]+');
|
||||
Route::post('r/invoices/{o}',[AdminController::class,'pay_invoices'])
|
||||
->where('o','[0-9]+')
|
||||
->middleware(['theme:adminlte-be','role:wholesaler']);
|
||||
|
@ -121,9 +121,6 @@ Route::group(['middleware'=>['auth','role:wholesaler'],'prefix'=>'a'],function()
|
||||
Route::get('report/accounts',[ReportController::class,'accounts']);
|
||||
Route::get('report/products',[ReportController::class,'products']);
|
||||
Route::get('report/services',[ReportController::class,'services']);
|
||||
// Charges - @todo This should probably go to resellers
|
||||
Route::match(['get','post'],'charge/addedit/{o?}',[AdminController::class,'charge_addedit']);
|
||||
Route::get('charge/unprocessed',[AdminController::class,'charge_unprocessed']);
|
||||
|
||||
// Payments - @todo This should probably go to resellers
|
||||
Route::match(['get','post'],'payment/addedit/{o?}',[AdminController::class,'pay_addedit']);
|
||||
@ -155,13 +152,15 @@ Route::group(['middleware'=>['auth','role:reseller'],'prefix'=>'r'],function() {
|
||||
});
|
||||
|
||||
// Charges
|
||||
Route::get('charges/{o}',[AdminController::class,'charge_pending_account'])
|
||||
->middleware('can:view,o')
|
||||
->where('o','[0-9]+');
|
||||
Route::post('charge/addedit',[ServiceController::class,'charge_addedit']);
|
||||
Route::post('charge/edit',[ServiceController::class,'charge_edit']);
|
||||
|
||||
// Reseller API calls
|
||||
Route::post('service_change_charges/{o}',[ServiceController::class,'service_change_charges_display'])
|
||||
->where('o','[0-9]+');
|
||||
|
||||
// Charges
|
||||
Route::view('report/charge/pending','theme.backend.adminlte.charge.pending');
|
||||
});
|
||||
|
||||
// Our User Routes
|
||||
|
Loading…
Reference in New Issue
Block a user