Merge pull request #17865 from grokability/show-inactive-licenses
Show inactive licenses
This commit is contained in:
@@ -26,6 +26,12 @@ class LicensesController extends Controller
|
||||
|
||||
$licenses = License::with('company', 'manufacturer', 'supplier','category', 'adminuser')->withCount('freeSeats as free_seats_count');
|
||||
|
||||
if ($request->input('status')=='inactive') {
|
||||
$licenses->ExpiredLicenses();
|
||||
} else {
|
||||
$licenses->ActiveLicenses();
|
||||
}
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$licenses->where('licenses.company_id', '=', $request->input('company_id'));
|
||||
}
|
||||
@@ -94,6 +100,8 @@ class LicensesController extends Controller
|
||||
$licenses->onlyTrashed();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $licenses->count()) ? $licenses->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
@@ -25,7 +25,7 @@ class LicenseCheckoutController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param $id
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @return \Illuminate\Contracts\View\View |\Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create(License $license)
|
||||
@@ -39,6 +39,11 @@ class LicenseCheckoutController extends Controller
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.not_enough_seats'));
|
||||
}
|
||||
|
||||
// Make sure the license is expired or terminated
|
||||
if ($license->isInactive()){
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.license_is_inactive'));
|
||||
}
|
||||
|
||||
// We don't currently allow checking out licenses to locations, so we'll reset that to user if needed
|
||||
if (session()->get('checkout_to_type') == 'location') {
|
||||
session()->put(['checkout_to_type' => 'user']);
|
||||
@@ -70,8 +75,19 @@ class LicenseCheckoutController extends Controller
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($license->availCount()->count() < 1) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.not_enough_seats'));
|
||||
}
|
||||
|
||||
// Make sure the license is expired or terminated
|
||||
if ($license->isInactive()) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.license_is_inactive'));
|
||||
}
|
||||
|
||||
$licenseSeat = $this->findLicenseSeatToCheckout($license, $seatId);
|
||||
$licenseSeat->created_by = auth()->id();
|
||||
$licenseSeat->notes = $request->input('notes');
|
||||
@@ -114,6 +130,7 @@ class LicenseCheckoutController extends Controller
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.not_enough_seats')));
|
||||
}
|
||||
|
||||
|
||||
if (! $licenseSeat->license->is($license)) {
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.mismatch')));
|
||||
}
|
||||
|
||||
@@ -31,11 +31,11 @@ class LicensesTransformer
|
||||
'purchase_order' => ($license->purchase_order) ? e($license->purchase_order) : null,
|
||||
'purchase_date' => Helper::getFormattedDateObject($license->purchase_date, 'date'),
|
||||
'termination_date' => Helper::getFormattedDateObject($license->termination_date, 'date'),
|
||||
'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'),
|
||||
'depreciation' => ($license->depreciation) ? ['id' => (int) $license->depreciation->id,'name'=> e($license->depreciation->name)] : null,
|
||||
'purchase_cost' => Helper::formatCurrencyOutput($license->purchase_cost),
|
||||
'purchase_cost_numeric' => $license->purchase_cost,
|
||||
'notes' => Helper::parseEscapedMarkedownInline($license->notes),
|
||||
'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'),
|
||||
'seats' => (int) $license->seats,
|
||||
'free_seats_count' => (int) $license->free_seats_count - License::unReassignableCount($license),
|
||||
'remaining' => (int) $license->free_seats_count,
|
||||
|
||||
@@ -299,16 +299,17 @@ class License extends Depreciable
|
||||
}
|
||||
|
||||
public function isInactive(): bool
|
||||
{
|
||||
$day = now()->startOfDay();
|
||||
{
|
||||
$day = now()->startOfDay();
|
||||
|
||||
$expired = $this->expiration_date && $this->asDateTime($this->expiration_date)->startofDay()->lessThanOrEqualTo($day);
|
||||
$expired = $this->expiration_date && $this->asDateTime($this->expiration_date)->startofDay()->lessThanOrEqualTo($day);
|
||||
|
||||
$terminated = $this->termination_date && $this->asDateTime($this->termination_date)->startofDay()->lessThanOrEqualTo($day);
|
||||
$terminated = $this->termination_date && $this->asDateTime($this->termination_date)->startofDay()->lessThanOrEqualTo($day);
|
||||
|
||||
|
||||
return $expired || $terminated;
|
||||
}
|
||||
return $expired || $terminated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets free_seat_count attribute
|
||||
*
|
||||
@@ -750,6 +751,38 @@ class License extends Depreciable
|
||||
->get();
|
||||
}
|
||||
|
||||
public function scopeActiveLicenses($query)
|
||||
{
|
||||
|
||||
return $query->whereNull('deleted_at')
|
||||
|
||||
// The termination date is null or within range
|
||||
->where(function ($query) {
|
||||
$query->whereNull('termination_date')
|
||||
->orWhereDate('termination_date', '>', [Carbon::now()]);
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('expiration_date')
|
||||
->orWhereDate('expiration_date', '>', [Carbon::now()]);
|
||||
});
|
||||
}
|
||||
|
||||
public function scopeExpiredLicenses($query)
|
||||
{
|
||||
|
||||
return $query->whereNull('deleted_at')
|
||||
|
||||
// The termination date is null or within range
|
||||
->where(function ($query) {
|
||||
$query->whereNull('termination_date')
|
||||
->orWhereDate('termination_date', '<=', [Carbon::now()]);
|
||||
})
|
||||
->orWhere(function ($query) {
|
||||
$query->whereNull('expiration_date')
|
||||
->orWhereDate('expiration_date', '<=', [Carbon::now()]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on manufacturer
|
||||
*
|
||||
|
||||
@@ -349,10 +349,19 @@ class BreadcrumbsServiceProvider extends ServiceProvider
|
||||
/**
|
||||
* Licenses Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('licenses.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.licenses'), route('licenses.index'))
|
||||
);
|
||||
if ((request()->is('licenses*')) && (request()->status=='inactive')) {
|
||||
Breadcrumbs::for('licenses.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.licenses'), route('licenses.index'))
|
||||
->push(trans('general.show_inactive'), route('licenses.index'))
|
||||
);
|
||||
} else {
|
||||
Breadcrumbs::for('licenses.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.licenses'), route('licenses.index'))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Breadcrumbs::for('licenses.create', fn (Trail $trail) =>
|
||||
$trail->parent('licenses.index', route('licenses.index'))
|
||||
|
||||
@@ -33,9 +33,9 @@ class LicenseFactory extends Factory
|
||||
'seats' => $this->faker->numberBetween(1, 10),
|
||||
'purchase_date' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get())->format('Y-m-d'),
|
||||
'order_number' => $this->faker->numberBetween(1000000, 50000000),
|
||||
'expiration_date' => $this->faker->dateTimeBetween('now', '+3 years', date_default_timezone_get())->format('Y-m-d H:i:s'),
|
||||
'expiration_date' => null,
|
||||
'reassignable' => $this->faker->boolean(),
|
||||
'termination_date' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get())->format('Y-m-d H:i:s'),
|
||||
'termination_date' => null,
|
||||
'supplier_id' => Supplier::factory(),
|
||||
'category_id' => Category::factory(),
|
||||
];
|
||||
|
||||
@@ -589,6 +589,7 @@ return [
|
||||
'components' => ':count Component|:count Components',
|
||||
],
|
||||
|
||||
'show_inactive' => 'Expired or Terminated',
|
||||
'more_info' => 'More Info',
|
||||
'quickscan_bulk_help' => 'Checking this box will edit the asset record to reflect this new location. Leaving it unchecked will simply note the location in the audit log. Note that if this asset is checked out, it will not change the location of the person, asset or location it is checked out to.',
|
||||
'whoops' => 'Whoops!',
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
id="licensesTable"
|
||||
data-buttons="licenseButtons"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.licenses.index') }}"
|
||||
data-url="{{ route('api.licenses.index', ['status' => e(request('status'))]) }}"
|
||||
data-export-options='{
|
||||
"fileName": "export-licenses-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
id="asssetModelsTable"
|
||||
data-buttons="modelButtons"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.models.index', ['status' => request('status')]) }}"
|
||||
data-url="{{ route('api.models.index', ['status' => e(request('status'))]) }}"
|
||||
data-export-options='{
|
||||
"fileName": "export-models-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
|
||||
@@ -557,12 +557,17 @@
|
||||
}
|
||||
|
||||
function licenseInOutFormatter(value, row) {
|
||||
if(row.disabled || row.user_can_checkout === false) {
|
||||
return '<a href="{{ config('app.url') }}/licenses/' + row.id + '/checkin" class="btn btn-sm bg-maroon disabled" data-tooltip="true" title="{{ trans('general.checkin_tooltip') }}">{{ trans('general.checkout') }}</a>';
|
||||
|
||||
// check that checkin is not disabled
|
||||
if (row.user_can_checkout === false) {
|
||||
return '<span class="btn btn-sm bg-maroon disabled" data-tooltip="true" title="{{ trans('admin/licenses/message.checkout.unavailable') }}">{{ trans('general.checkout') }}</span>';
|
||||
} else if (row.disabled === true) {
|
||||
return '<span class="btn btn-sm bg-maroon disabled" data-tooltip="true" title="{{ trans('admin/licenses/message.checkout.license_is_inactive') }}">{{ trans('general.checkout') }}</span>';
|
||||
|
||||
} else
|
||||
// The user is allowed to check the license seat out and it's available
|
||||
if ((row.available_actions.checkout === true) && (row.user_can_checkout === true)) {
|
||||
return '<a href="{{ config('app.url') }}/licenses/' + row.id + '/checkout/'+row.id+'" class="btn btn-sm bg-maroon" data-tooltip="true" title="{{ trans('general.checkout_tooltip') }}">{{ trans('general.checkout') }}</a>';
|
||||
if ((row.available_actions.checkout === true) && (row.user_can_checkout === true) && (row.disabled === false)) {
|
||||
return '<a href="{{ config('app.url') }}/licenses/' + row.id + '/checkout/" class="btn btn-sm bg-maroon" data-tooltip="true" title="{{ trans('general.checkout_tooltip') }}">{{ trans('general.checkout') }}</a>';
|
||||
}
|
||||
}
|
||||
// We need a special formatter for license seats, since they don't work exactly the same
|
||||
@@ -572,7 +577,7 @@
|
||||
if (row.disabled && (row.assigned_user || row.assigned_asset)) {
|
||||
return '<a href="{{ config('app.url') }}/licenses/' + row.id + '/checkin" class="btn btn-sm bg-purple" data-tooltip="true" title="{{ trans('general.checkin_tooltip') }}">{{ trans('general.checkin') }}</a>';
|
||||
}
|
||||
if(row.disabled) {
|
||||
if (row.disabled) {
|
||||
return '<a href="{{ config('app.url') }}/licenses/' + row.id + '/checkin" class="btn btn-sm bg-maroon disabled" data-tooltip="true" title="{{ trans('general.checkin_tooltip') }}">{{ trans('general.checkout') }}</a>';
|
||||
}
|
||||
// The user is allowed to check the license seat out and it's available
|
||||
@@ -580,6 +585,11 @@
|
||||
return '<a href="{{ config('app.url') }}/licenses/' + row.license_id + '/checkout/'+row.id+'" class="btn btn-sm bg-maroon" data-tooltip="true" title="{{ trans('general.checkout_tooltip') }}">{{ trans('general.checkout') }}</a>';
|
||||
}
|
||||
|
||||
// The user is allowed to check the license seat in and it's available
|
||||
if ((row.available_actions.checkin === true) && ((row.assigned_asset) || (row.assigned_user))) {
|
||||
return '<a href="{{ config('app.url') }}/licenses/' + row.id + '/checkin/" class="btn btn-sm bg-purple" data-tooltip="true" title="{{ trans('general.checkin_tooltip') }}">{{ trans('general.checkin') }}</a>';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function genericCheckinCheckoutFormatter(destination) {
|
||||
@@ -1775,7 +1785,19 @@
|
||||
attributes: {
|
||||
title: '{{ trans('general.export') }}'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
btnShowInactive: {
|
||||
text: '{{ (request()->input('status') == "inactive") ? trans('general.list_all') : trans('general.show_inactive') }}',
|
||||
icon: 'fas fa-clock {{ (request()->input('status') == "inactive") ? ' text-danger' : '' }}',
|
||||
event () {
|
||||
window.location.href = '{{ (request()->input('status') == "inactive") ? route('licenses.index') : route('licenses.index', ['status' => 'inactive']) }}';
|
||||
},
|
||||
attributes: {
|
||||
title: '{{ (request()->input('status') == "inactive") ? trans('general.list_all') : trans('general.show_inactive') }}',
|
||||
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -897,7 +897,7 @@
|
||||
</td>
|
||||
<td class="hidden-print col-md-2">
|
||||
@can('update', $license)
|
||||
<a href="{{ route('licenses.checkin', $license->pivot->id, ['backto'=>'user']) }}" class="btn btn-primary btn-sm hidden-print">{{ trans('general.checkin') }}</a>
|
||||
<a href="{{ route('licenses.checkin', $license->pivot->id, ['backto'=>'user']) }}" class="btn bg-purple btn-sm hidden-print">{{ trans('general.checkin') }}</a>
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user