mirror of
https://github.com/grokability/snipe-it.git
synced 2026-03-12 17:52:00 +08:00
Merge remote-tracking branch 'origin/develop'
This commit is contained in:
@@ -60,19 +60,57 @@ class SendExpirationAlerts extends Command
|
||||
Mail::to($recipients)->send(new ExpiringAssetsMail($assets, $alert_interval));
|
||||
|
||||
$this->table(
|
||||
['ID', 'Tag', 'Model', 'Model Number', 'EOL', 'EOL Months', 'Warranty Expires', 'Warranty Months'],
|
||||
$assets->map(fn($item) => ['ID' => $item->id, 'Tag' => $item->asset_tag, 'Model' => $item->model->name, 'Model Number' => $item->model->model_number, 'EOL' => $item->asset_eol_date, 'EOL Months' => $item->model->eol, 'Warranty Expires' => $item->warranty_expires, 'Warranty Months' => $item->warranty_months])
|
||||
);
|
||||
[
|
||||
trans('general.id'),
|
||||
trans('admin/hardware/form.tag'),
|
||||
trans('admin/hardware/form.model'),
|
||||
trans('general.model_no'),
|
||||
trans('general.purchase_date'),
|
||||
trans('admin/hardware/form.eol_rate'),
|
||||
trans('admin/hardware/form.eol_date'),
|
||||
trans('admin/hardware/form.warranty_expires'),
|
||||
],
|
||||
$assets->map(fn($item) =>
|
||||
[
|
||||
trans('general.id') => $item->id,
|
||||
trans('admin/hardware/form.tag') => $item->asset_tag,
|
||||
trans('admin/hardware/form.model') => $item->model->name,
|
||||
trans('general.model_no') => $item->model->model_number,
|
||||
trans('general.purchase_date') => $item->purchase_date_formatted,
|
||||
trans('admin/hardware/form.eol_rate') => $item->model->eol,
|
||||
trans('admin/hardware/form.eol_date') => $item->eol_date ? $item->eol_formatted_date .' ('.$item->eol_diff_for_humans.')' : '',
|
||||
trans('admin/hardware/form.warranty_expires') => $item->warranty_expires ? $item->warranty_expires_formatted_date .' ('.$item->warranty_expires_diff_for_humans.')' : '',
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
// Expiring licenses
|
||||
$licenses = License::getExpiringLicenses($alert_interval);
|
||||
$licenses = License::query()->ExpiringLicenses($alert_interval)
|
||||
->with('manufacturer','category')
|
||||
->orderBy('expiration_date', 'ASC')
|
||||
->orderBy('termination_date', 'ASC')
|
||||
->get();
|
||||
if ($licenses->count() > 0) {
|
||||
Mail::to($recipients)->send(new ExpiringLicenseMail($licenses, $alert_interval));
|
||||
|
||||
$this->table(
|
||||
['ID', 'Name', 'Expires', 'Termination Date'],
|
||||
$licenses->map(fn($item) => ['ID' => $item->id, 'Name' => $item->name, 'Expires' => $item->expiration_date, 'Termination Date' => $item->termination_date])
|
||||
[
|
||||
trans('general.id'),
|
||||
trans('general.name'),
|
||||
trans('general.purchase_date'),
|
||||
trans('admin/licenses/form.expiration'),
|
||||
trans('mail.expires'),
|
||||
trans('admin/licenses/form.termination_date'),
|
||||
trans('mail.terminates')],
|
||||
$licenses->map(fn($item) => [
|
||||
trans('general.id') => $item->id,
|
||||
trans('general.name') => $item->name,
|
||||
trans('general.purchase_date') => $item->purchase_date_formatted,
|
||||
trans('admin/licenses/form.expiration') => $item->expires_formatted_date,
|
||||
trans('mail.expires') => $item->expires_diff_for_humans,
|
||||
trans('admin/licenses/form.termination_date') => $item->terminates_formatted_date,
|
||||
trans('mail.terminates') => $item->terminates_diff_for_humans
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\LicensesTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Models\License;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -25,9 +26,12 @@ class LicensesController extends Controller
|
||||
$this->authorize('view', License::class);
|
||||
|
||||
$licenses = License::with('company', 'manufacturer', 'supplier','category', 'adminuser')->withCount('freeSeats as free_seats_count');
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
if ($request->input('status')=='inactive') {
|
||||
$licenses->ExpiredLicenses();
|
||||
} elseif ($request->input('status')=='expiring') {
|
||||
$licenses->ExpiringLicenses($settings->alert_interval);
|
||||
} else {
|
||||
$licenses->ActiveLicenses();
|
||||
}
|
||||
|
||||
@@ -227,7 +227,6 @@ class Asset extends Depreciable
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function customFieldValidationRules()
|
||||
{
|
||||
|
||||
@@ -266,7 +265,6 @@ class Asset extends Depreciable
|
||||
return parent::save($params);
|
||||
}
|
||||
|
||||
|
||||
public function getDisplayNameAttribute()
|
||||
{
|
||||
return $this->present()->name();
|
||||
@@ -277,20 +275,79 @@ class Asset extends Depreciable
|
||||
*
|
||||
* @return \Carbon\Carbon|null
|
||||
*/
|
||||
public function getWarrantyExpiresAttribute()
|
||||
|
||||
|
||||
protected function warrantyExpires(): Attribute
|
||||
{
|
||||
if (isset($this->attributes['warranty_months']) && isset($this->attributes['purchase_date'])) {
|
||||
if (is_string($this->attributes['purchase_date']) || is_string($this->attributes['purchase_date'])) {
|
||||
$purchase_date = \Carbon\Carbon::parse($this->attributes['purchase_date']);
|
||||
} else {
|
||||
$purchase_date = \Carbon\Carbon::instance($this->attributes['purchase_date']);
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => ($attributes['warranty_months'] && $attributes['purchase_date']) ? Carbon::parse($attributes['purchase_date'])->addMonths($attributes['warranty_months']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
protected function warrantyExpiresFormattedDate(): Attribute
|
||||
{
|
||||
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => Helper::getFormattedDateObject($this->warrantyExpires, 'date', false)
|
||||
);
|
||||
}
|
||||
|
||||
protected function warrantyExpiresDiff(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $this->warrantyExpires ? round((Carbon::now()->diffInDays($this->warrantyExpires))) : null,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
protected function warrantyExpiresDiffForHumans(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $this->warrantyExpires ? Carbon::parse($this->warrantyExpires)->diffForHumans() : null,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
protected function eolDate(): Attribute
|
||||
{
|
||||
|
||||
return Attribute:: make(
|
||||
get: function(mixed $value, array $attributes) {
|
||||
if ($attributes['asset_eol_date'] && $attributes['eol_explicit'] == '1') {
|
||||
return Carbon::parse($attributes['asset_eol_date']);
|
||||
} elseif ($attributes['purchase_date'] && $this->model && ((int) $this->model->eol > 0)) {
|
||||
return Carbon::parse($attributes['purchase_date'])->addMonths((int) $this->model->eol);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
$purchase_date->setTime(0, 0, 0);
|
||||
);
|
||||
|
||||
return $purchase_date->addMonths((int) $this->attributes['warranty_months']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function eolFormattedDate(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $this->eolDate ? Helper::getFormattedDateObject($this->eolDate, 'date', false) : null,
|
||||
);
|
||||
}
|
||||
|
||||
protected function eolDiffInDays(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $this->eolDate ? round((Carbon::now()->diffInDays(Carbon::parse($this->eolDate), false, 1))) : null,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
protected function eolDiffForHumans(): Attribute
|
||||
{
|
||||
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $this->eolDate ? Carbon::parse($this->eolDate)->diffForHumans() : null,
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Models\Traits\HasUploads;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -156,6 +157,29 @@ class License extends Depreciable
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected function terminatesFormattedDate(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $attributes['termination_date'] ? Helper::getFormattedDateObject($attributes['termination_date'], 'date', false) : null,
|
||||
);
|
||||
}
|
||||
|
||||
protected function terminatesDiffInDays(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $attributes['termination_date'] ? Carbon::now()->diffInDays($attributes['termination_date']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
protected function terminatesDiffForHumans(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $attributes['termination_date'] ? Carbon::parse($attributes['termination_date'])->diffForHumans() : null,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function prepareLimitChangeRule($parameters, $field)
|
||||
{
|
||||
$actual_seat_count = $this->licenseseats()->count(); //we use the *actual* seat count here, in case your license has gone wonky
|
||||
@@ -706,49 +730,6 @@ class License extends Depreciable
|
||||
return $this->hasMany(\App\Models\LicenseSeat::class)->whereNull('assigned_to')->whereNull('deleted_at')->whereNull('asset_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns expiring licenses.
|
||||
*
|
||||
* This checks if:
|
||||
*
|
||||
* 1) The license has not been deleted
|
||||
* 2) The expiration date is between now and the number of days specified
|
||||
* 3) There is an expiration date set and the termination date has not passed
|
||||
* 4) The license termination date is null or has not passed
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
* @see \App\Console\Commands\SendExpiringLicenseNotifications
|
||||
*/
|
||||
public static function getExpiringLicenses($days = 60)
|
||||
{
|
||||
|
||||
return self::whereNull('licenses.deleted_at')
|
||||
|
||||
// The termination date is null or within range
|
||||
->where(function ($query) use ($days) {
|
||||
$query->whereNull('termination_date')
|
||||
->orWhereBetween('termination_date', [Carbon::now(), Carbon::now()->addDays($days)]);
|
||||
})
|
||||
->where(function ($query) use ($days) {
|
||||
$query->whereNotNull('expiration_date')
|
||||
// Handle expired licenses without termination dates
|
||||
->where(function ($query) use ($days) {
|
||||
$query->whereNull('termination_date')
|
||||
->whereBetween('expiration_date', [Carbon::now(), Carbon::now()->addDays($days)]);
|
||||
})
|
||||
|
||||
// Handle expired licenses with termination dates in the future
|
||||
->orWhere(function ($query) use ($days) {
|
||||
$query->whereBetween('termination_date', [Carbon::now(), Carbon::now()->addDays($days)]);
|
||||
});
|
||||
})
|
||||
->orderBy('expiration_date', 'ASC')
|
||||
->orderBy('termination_date', 'ASC')
|
||||
->get();
|
||||
}
|
||||
|
||||
public function scopeActiveLicenses($query)
|
||||
{
|
||||
|
||||
@@ -765,19 +746,57 @@ class License extends Depreciable
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Expiried/terminated licenses scope
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
* @see \App\Console\Commands\SendExpiringLicenseNotifications
|
||||
*/
|
||||
public function scopeExpiredLicenses($query)
|
||||
{
|
||||
return $query->whereDate('termination_date', '<=', Carbon::now())// The termination date is null or within range
|
||||
->orWhere(function ($query) {
|
||||
$query->whereDate('expiration_date', '<=', Carbon::now());
|
||||
})
|
||||
->whereNull('deleted_at');
|
||||
}
|
||||
|
||||
return $query->whereNull('licenses.deleted_at')
|
||||
/**
|
||||
* Expiring/terminating licenses scope
|
||||
*
|
||||
* This checks if:
|
||||
*
|
||||
* 1) The license has not been deleted
|
||||
* 2) The expiration date is between now and the number of days specified
|
||||
* 3) There is an expiration date set and the termination date has not passed
|
||||
* 4) The license termination date is null or has not passed
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
* @see \App\Console\Commands\SendExpiringLicenseNotifications
|
||||
*/
|
||||
public function scopeExpiringLicenses($query, $days = 60)
|
||||
{
|
||||
return $query// The termination date is null or within range
|
||||
->where(function ($query) use ($days) {
|
||||
$query->whereNull('termination_date')
|
||||
->orWhereBetween('termination_date', [Carbon::now(), Carbon::now()->addDays($days)]);
|
||||
})
|
||||
->where(function ($query) use ($days) {
|
||||
$query->whereNotNull('expiration_date')
|
||||
// Handle expiring licenses without termination dates
|
||||
->where(function ($query) use ($days) {
|
||||
$query->whereNull('termination_date')
|
||||
->whereBetween('expiration_date', [Carbon::now(), Carbon::now()->addDays($days)]);
|
||||
})
|
||||
|
||||
// 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()]);
|
||||
// Handle expiring licenses with termination dates in the future
|
||||
->orWhere(function ($query) use ($days) {
|
||||
$query->whereBetween('termination_date', [Carbon::now(), Carbon::now()->addDays($days)]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@@ -19,6 +20,37 @@ class SnipeModel extends Model
|
||||
$this->attributes['purchase_date'] = $value;
|
||||
}
|
||||
|
||||
|
||||
protected function purchaseDateFormatted(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $attributes['purchase_date'] ? Helper::getFormattedDateObject(Carbon::parse($attributes['purchase_date']), 'date', false) : null,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected function expiresDiffInDays(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $attributes['expiration_date'] ? Carbon::now()->diffInDays($attributes['expiration_date']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected function expiresDiffForHumans(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $attributes['expiration_date'] ? Carbon::parse($attributes['expiration_date'])->diffForHumans() : null,
|
||||
);
|
||||
}
|
||||
|
||||
protected function expiresFormattedDate(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value, array $attributes) => $attributes['expiration_date'] ? Helper::getFormattedDateObject($attributes['expiration_date'], 'date', false) : null,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
@@ -180,6 +212,7 @@ class SnipeModel extends Model
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function getEula()
|
||||
{
|
||||
|
||||
|
||||
@@ -48,6 +48,13 @@ class LicensePresenter extends Presenter
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/licenses/form.expiration'),
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
], [
|
||||
'field' => 'termination_date',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('admin/licenses/form.termination_date'),
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
], [
|
||||
'field' => 'license_email',
|
||||
'searchable' => true,
|
||||
@@ -110,14 +117,6 @@ class LicensePresenter extends Presenter
|
||||
'title' => trans('general.purchase_date'),
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'termination_date',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('admin/licenses/form.termination_date'),
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'depreciation',
|
||||
'searchable' => true,
|
||||
|
||||
@@ -350,10 +350,15 @@ class BreadcrumbsServiceProvider extends ServiceProvider
|
||||
* Licenses Breadcrumbs
|
||||
*/
|
||||
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'))
|
||||
);
|
||||
} elseif ((request()->is('licenses*')) && (request()->status=='expiring')) {
|
||||
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'))
|
||||
->push(trans('general.show_expiring'), route('licenses.index'))
|
||||
);
|
||||
} else {
|
||||
Breadcrumbs::for('licenses.index', fn (Trail $trail) =>
|
||||
|
||||
@@ -398,6 +398,7 @@ return [
|
||||
'permissions' => 'Permissions',
|
||||
'managed_ldap' => '(Managed via LDAP)',
|
||||
'export' => 'Export',
|
||||
'export_all_to_csv' => 'Export all to CSV',
|
||||
'ldap_sync' => 'LDAP Sync',
|
||||
'ldap_user_sync' => 'LDAP User Sync',
|
||||
'synchronize' => 'Synchronize',
|
||||
@@ -595,6 +596,7 @@ return [
|
||||
],
|
||||
|
||||
'show_inactive' => 'Expired or Terminated',
|
||||
'show_expiring' => 'Expiring or Terminating Soon',
|
||||
'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!',
|
||||
|
||||
@@ -59,6 +59,7 @@ return [
|
||||
'days' => 'Days',
|
||||
'expecting_checkin_date' => 'Expected Checkin Date',
|
||||
'expires' => 'Expires',
|
||||
'terminates' => 'Terminates',
|
||||
'following_accepted' => 'The following was accepted',
|
||||
'following_declined' => 'The following was declined',
|
||||
'hello' => 'Hello',
|
||||
|
||||
@@ -63,7 +63,6 @@
|
||||
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
|
||||
data-cookie-id-table="{{ request()->has('status') ? e(request()->input('status')) : '' }}assetsListingTable"
|
||||
data-id-table="{{ request()->has('status') ? e(request()->input('status')) : '' }}assetsListingTable"
|
||||
data-search-text="{{ e(Session::get('search')) }}"
|
||||
data-side-pagination="server"
|
||||
data-show-footer="true"
|
||||
data-sort-order="asc"
|
||||
|
||||
@@ -1,38 +1,22 @@
|
||||
@component('mail::message')
|
||||
{{ trans_choice('mail.assets_warrantee_alert', $assets->count(), ['count'=>$assets->count(), 'threshold' => $threshold]) }}
|
||||
|
||||
<style>
|
||||
|
||||
th, td {
|
||||
vertical-align: top;
|
||||
}
|
||||
hr {
|
||||
display: block;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
border-top: 1px solid #ccc;
|
||||
margin: 1em 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<x-mail::table>
|
||||
|
||||
| | | |
|
||||
| ------------- | ------------- | ------------- |
|
||||
@foreach ($assets as $asset)
|
||||
@php
|
||||
$warranty_expires = \App\Helpers\Helper::getFormattedDateObject($asset->present()->warranty_expires, 'date');
|
||||
$eol_date = \App\Helpers\Helper::getFormattedDateObject($asset->asset_eol_date, 'date');
|
||||
$warranty_diff = ($asset->present()->warranty_expires) ? round(\Carbon\Carbon::now()->diffInDays(\Carbon\Carbon::parse($warranty_expires['date']), false), 1) : '';
|
||||
$eol_diff = round(\Carbon\Carbon::now()->diffInDays(\Carbon\Carbon::parse($asset->asset_eol_date), false), 1);
|
||||
$icon = ($warranty_diff <= $threshold && $warranty_diff >= 0) ? '⚠️' : (($eol_diff <= $threshold && $eol_diff >= 0) ? '🚨' : 'ℹ️');
|
||||
@endphp
|
||||
| {{ $icon }} **{{ trans('mail.name') }}** | <a href="{{ route('hardware.show', $asset->id) }}">{{ $asset->display_name }}</a> <br><small>{{trans('mail.serial').': '.$asset->serial}}</small> |
|
||||
@if ($warranty_expires)
|
||||
| **{{ trans('mail.expires') }}** | {{ !is_null($warranty_expires) ? $warranty_expires['formatted'] : '' }} (<strong>{{ $warranty_diff }} {{ trans('mail.Days') }}</strong>) |
|
||||
| {{ ($asset->eol_diff_in_days <= ($threshold / 2)) ? '🚨' : (($asset->eol_diff_in_days <= $threshold) ? '⚠️' : 'ℹ️ ') }} **{{ trans('mail.name') }}** | <a href="{{ route('hardware.show', $asset->id) }}">{{ $asset->display_name }}</a> |
|
||||
@if ($asset->serial)
|
||||
| **{{ trans('general.serial_number') }}** | {{ $asset->serial }} |
|
||||
@endif
|
||||
@if ($eol_date)
|
||||
| **{{ trans('mail.eol') }}** | {{ !is_null($eol_date) ? $eol_date['formatted'] : '' }} (<strong>{{ $eol_diff }} {{ trans('mail.Days') }}</strong>) |
|
||||
@if ($asset->purchase_date)
|
||||
| **{{ trans('general.purchase_date') }}** | {{ $asset->purchase_date_formatted }} |
|
||||
@endif
|
||||
@if ($asset->warranty_expires)
|
||||
| **{{ trans('mail.expires') }}** | {{ $asset->warranty_expires_formatted_date }} ({{ $asset->warranty_expires_diff_for_humans }}) |
|
||||
@endif
|
||||
@if ($asset->eol_date && $asset->eol_diff_for_humans)
|
||||
| **{{ trans('mail.eol') }}** | {{ $asset->eol_formatted_date }} ({{ $asset->eol_diff_for_humans }}) |
|
||||
@endif
|
||||
@if ($asset->supplier)
|
||||
| **{{ trans('mail.supplier') }}** | {{ ($asset->supplier ? e($asset->supplier->name) : '') }} |
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
@component('mail::message')
|
||||
{{ trans_choice('mail.license_expiring_alert', $licenses->count(), ['count'=>$licenses->count(), 'threshold' => $threshold]) }}
|
||||
@component('mail::table')
|
||||
|
||||
<table width="100%">
|
||||
<tr><td> </td><td>{{ trans('mail.name') }}</td><td>{{ trans('mail.Days') }}</td><td>{{ trans('mail.expires') }}</td></tr>
|
||||
<x-mail::table>
|
||||
|
||||
| | {{ trans('mail.name') }} | {{ trans('general.category') }} | {{ trans('mail.expires') }} | {{ trans('mail.terminates') }} |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
@foreach ($licenses as $license)
|
||||
@php
|
||||
$expires = Helper::getFormattedDateObject($license->expiration_date, 'date');
|
||||
$diff = round(abs(strtotime($license->expiration_date->format('Y-m-d')) - strtotime(date('Y-m-d')))/86400);
|
||||
$icon = ($diff <= ($threshold / 2)) ? '🚨' : (($diff <= $threshold) ? '⚠️' : ' ');
|
||||
@endphp
|
||||
<tr><td>{{ $icon }} </td><td> <a href="{{ route('licenses.show', $license->id) }}">{{ $license->name }}</a> </td><td> {{ $diff }} {{ trans('mail.Days') }} </td><td>{{ $expires['formatted'] }}</td></tr>
|
||||
| {{ (($license->isExpired()) || ($license->isTerminated()) || ($license->terminates_diff_in_days <= ($threshold / 2)) || ($license->expires_diff_in_days <= ($threshold / 2))) ? '🚨' : (($license->expires_diff_in_days <= $threshold) ? '⚠️' : 'ℹ️ ') }} | <a href="{{ route('licenses.show', $license->id) }}">{{ $license->name }}</a> {{ $license->manufacturer ? '('.$license->manufacturer->name.')' : '' }} | {{ $license->category ? $license->category->name : '' }} | {{ $license->expires_formatted_date }} {!! $license->expires_diff_for_humans ? ' ('.$license->expires_diff_for_humans .')' : '' !!} | {{ $license->terminates_formatted_date }} {{ $license->terminates_diff_for_humans ? ' ('.$license->terminates_diff_for_humans .')' : '' }}|
|
||||
| <hr> | <hr> | <hr> | <hr> | <hr> |
|
||||
@endforeach
|
||||
</table>
|
||||
</x-mail::table>
|
||||
@endcomponent
|
||||
@endcomponent
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,7 @@
|
||||
data-toolbar="#userBulkEditToolbar"
|
||||
data-bulk-button-id="#bulkUserEditButton"
|
||||
data-bulk-form-id="#usersBulkForm"
|
||||
data-show-columns-search="true"
|
||||
id="usersTable"
|
||||
data-buttons="userButtons"
|
||||
class="table table-striped snipe-table"
|
||||
|
||||
@@ -3,7 +3,20 @@
|
||||
@slot('header')
|
||||
|
||||
{{-- Check that the $snipeSettings variable is set, images are set to be shown, and setup is complete --}}
|
||||
<style>
|
||||
|
||||
th, td {
|
||||
vertical-align: top;
|
||||
}
|
||||
hr {
|
||||
display: block;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
border-top: 1px solid #edeff2;
|
||||
margin: 1em 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@if (isset($snipeSettings) && ($snipeSettings::setupCompleted()))
|
||||
|
||||
|
||||
@@ -10,9 +10,12 @@ class SnipeModelTest extends TestCase
|
||||
{
|
||||
$c = new SnipeModel;
|
||||
$c->purchase_date = '';
|
||||
$this->assertTrue($c->purchase_date === null);
|
||||
$c->purchase_date = '2016-03-25 12:35:50';
|
||||
$this->assertTrue($c->purchase_date === '2016-03-25 12:35:50');
|
||||
$this->assertNull($c->purchase_date);
|
||||
$c->purchase_date = null;
|
||||
$this->assertNull($c->purchase_date);
|
||||
$c->purchase_date = '2016-03-25';
|
||||
$this->assertTrue($c->purchase_date === '2016-03-25');
|
||||
$this->assertEquals('2016-03-25', $c->purchase_date);
|
||||
}
|
||||
|
||||
public function testSetsPurchaseCostsAppropriately()
|
||||
|
||||
Reference in New Issue
Block a user