mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-09 23:24:06 -08:00
Merge branch 'develop' into snipeit_v7_laravel10
This commit is contained in:
commit
5b02a43957
|
@ -3018,6 +3018,87 @@
|
|||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "koiakoia",
|
||||
"name": "koiakoia",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/60405354?v=4",
|
||||
"profile": "https://github.com/koiakoia",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mustafa-online",
|
||||
"name": "Mustafa Online",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5323832?v=4",
|
||||
"profile": "https://github.com/mustafa-online",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "franceslui",
|
||||
"name": "franceslui",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/104601439?v=4",
|
||||
"profile": "https://github.com/franceslui",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Q4kK",
|
||||
"name": "Q4kK",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/125313163?v=4",
|
||||
"profile": "https://github.com/Q4kK",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "squintfox",
|
||||
"name": "squintfox",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/55590532?v=4",
|
||||
"profile": "https://github.com/squintfox",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jeffclay",
|
||||
"name": "Jeff Clay",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1380084?v=4",
|
||||
"profile": "https://github.com/jeffclay",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "PP-JN-RL",
|
||||
"name": "Phil J R",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/52716446?v=4",
|
||||
"profile": "https://github.com/PP-JN-RL",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "chandanchowdhury",
|
||||
"name": "i_virus",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1496725?v=4",
|
||||
"profile": "https://www.corelight.com/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "gitgrimbo",
|
||||
"name": "Paul Grime",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1020541?v=4",
|
||||
"profile": "https://github.com/gitgrimbo",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -432,6 +432,17 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
|||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bilias"><img src="https://avatars.githubusercontent.com/u/47315739?v=4?s=110" width="110px;" alt="bilias"/><br /><sub><b>bilias</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=bilias" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/coach1988"><img src="https://avatars.githubusercontent.com/u/2565989?v=4?s=110" width="110px;" alt="coach1988"/><br /><sub><b>coach1988</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=coach1988" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mauro-miatello"><img src="https://avatars.githubusercontent.com/u/11910225?v=4?s=110" width="110px;" alt="MrM"/><br /><sub><b>MrM</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mauro-miatello" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/koiakoia"><img src="https://avatars.githubusercontent.com/u/60405354?v=4?s=110" width="110px;" alt="koiakoia"/><br /><sub><b>koiakoia</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=koiakoia" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mustafa-online"><img src="https://avatars.githubusercontent.com/u/5323832?v=4?s=110" width="110px;" alt="Mustafa Online"/><br /><sub><b>Mustafa Online</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mustafa-online" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/franceslui"><img src="https://avatars.githubusercontent.com/u/104601439?v=4?s=110" width="110px;" alt="franceslui"/><br /><sub><b>franceslui</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=franceslui" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Q4kK"><img src="https://avatars.githubusercontent.com/u/125313163?v=4?s=110" width="110px;" alt="Q4kK"/><br /><sub><b>Q4kK</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Q4kK" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/squintfox"><img src="https://avatars.githubusercontent.com/u/55590532?v=4?s=110" width="110px;" alt="squintfox"/><br /><sub><b>squintfox</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=squintfox" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jeffclay"><img src="https://avatars.githubusercontent.com/u/1380084?v=4?s=110" width="110px;" alt="Jeff Clay"/><br /><sub><b>Jeff Clay</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jeffclay" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PP-JN-RL"><img src="https://avatars.githubusercontent.com/u/52716446?v=4?s=110" width="110px;" alt="Phil J R"/><br /><sub><b>Phil J R</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=PP-JN-RL" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.corelight.com/"><img src="https://avatars.githubusercontent.com/u/1496725?v=4?s=110" width="110px;" alt="i_virus"/><br /><sub><b>i_virus</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=chandanchowdhury" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gitgrimbo"><img src="https://avatars.githubusercontent.com/u/1020541?v=4?s=110" width="110px;" alt="Paul Grime"/><br /><sub><b>Paul Grime</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=gitgrimbo" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -12,7 +12,7 @@ It is built on [Laravel 8](http://laravel.com).
|
|||
Snipe-IT is actively developed and we [release quite frequently](https://github.com/snipe/snipe-it/releases). ([Check out the live demo here](https://snipeitapp.com/demo/).)
|
||||
|
||||
> [!TIP]
|
||||
> __This is web-based software__. This means there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
|
||||
> __This is web-based software__. This means there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, any flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
|
||||
|
||||
-----
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ use App\Notifications\ExpectedCheckinAdminNotification;
|
|||
use App\Notifications\ExpectedCheckinNotification;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SendExpectedCheckinAlerts extends Command
|
||||
{
|
||||
|
@ -43,25 +42,31 @@ class SendExpectedCheckinAlerts extends Command
|
|||
public function handle()
|
||||
{
|
||||
$settings = Setting::getSettings();
|
||||
$whenNotify = Carbon::now();
|
||||
$assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
|
||||
$interval = $settings->audit_warning_days ?? 0;
|
||||
$today = Carbon::now();
|
||||
$interval_date = $today->copy()->addDays($interval);
|
||||
|
||||
$assets = Asset::whereNull('deleted_at')->DueOrOverdueForCheckin($settings)->orderBy('assets.expected_checkin', 'desc')->get();
|
||||
|
||||
$this->info($assets->count().' assets must be checked in on or before '.$interval_date.' is deadline');
|
||||
|
||||
$this->info($whenNotify.' is deadline');
|
||||
$this->info($assets->count().' assets');
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
if ($asset->assigned && $asset->checkedOutToUser()) {
|
||||
Log::info('Sending ExpectedCheckinNotification to ' . $asset->assigned->email);
|
||||
$asset->assigned->notify((new ExpectedCheckinNotification($asset)));
|
||||
if ($asset->assignedTo && (isset($asset->assignedTo->email)) && ($asset->assignedTo->email!='') && $asset->checkedOutToUser()) {
|
||||
$this->info('Sending User ExpectedCheckinNotification to: '.$asset->assignedTo->email);
|
||||
$asset->assignedTo->notify((new ExpectedCheckinNotification($asset)));
|
||||
}
|
||||
}
|
||||
|
||||
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
||||
// Send a rollup to the admin, if settings dictate
|
||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
|
||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item) {
|
||||
return new AlertRecipient($item);
|
||||
});
|
||||
|
||||
$this->info('Sending Admin ExpectedCheckinNotification to: '.$settings->alert_email);
|
||||
\Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\License;
|
||||
use App\Models\Recipients;
|
||||
use App\Models\Recipients\AlertRecipient;
|
||||
use App\Models\Setting;
|
||||
use App\Notifications\ExpiringAssetsNotification;
|
||||
use App\Notifications\SendUpcomingAuditNotification;
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
|
@ -45,40 +43,26 @@ class SendUpcomingAuditReport extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$interval = $settings->audit_warning_days ?? 0;
|
||||
$today = Carbon::now();
|
||||
$interval_date = $today->copy()->addDays($interval);
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
$assets = Asset::whereNull('deleted_at')->DueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'desc')->get();
|
||||
$this->info($assets->count().' assets must be audited in on or before '.$interval_date.' is deadline');
|
||||
|
||||
if (($settings->alert_email != '') && ($settings->audit_warning_days) && ($settings->alerts_enabled == 1)) {
|
||||
|
||||
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
||||
// Send a rollup to the admin, if settings dictate
|
||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
|
||||
return new \App\Models\Recipients\AlertRecipient($item);
|
||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item) {
|
||||
return new AlertRecipient($item);
|
||||
});
|
||||
|
||||
// Assets due for auditing
|
||||
$this->info('Sending Admin SendUpcomingAuditNotification to: '.$settings->alert_email);
|
||||
\Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
|
||||
|
||||
$assets = Asset::whereNotNull('next_audit_date')
|
||||
->DueOrOverdueForAudit($settings)
|
||||
->orderBy('last_audit_date', 'asc')->get();
|
||||
|
||||
if ($assets->count() > 0) {
|
||||
$this->info(trans_choice('mail.upcoming-audits', $assets->count(),
|
||||
['count' => $assets->count(), 'threshold' => $settings->audit_warning_days]));
|
||||
\Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
|
||||
$this->info('Audit report sent to '.$settings->alert_email);
|
||||
} else {
|
||||
$this->info('No assets to be audited. No report sent.');
|
||||
}
|
||||
} elseif ($settings->alert_email == '') {
|
||||
$this->error('Could not send email. No alert email configured in settings');
|
||||
} elseif (! $settings->audit_warning_days) {
|
||||
$this->error('No audit warning days set in Admin Notifications. No mail will be sent.');
|
||||
} elseif ($settings->alerts_enabled != 1) {
|
||||
$this->info('Alerts are disabled in the settings. No mail will be sent');
|
||||
} else {
|
||||
$this->error('Something went wrong. :( ');
|
||||
$this->error('Admin Notifications Email Setting: '.$settings->alert_email);
|
||||
$this->error('Admin Audit Warning Setting: '.$settings->audit_warning_days);
|
||||
$this->error('Admin Alerts Emnabled: '.$settings->alerts_enabled);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class AssetsController extends Controller
|
|||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(Request $request, $audit = null)
|
||||
public function index(Request $request, $action = null, $upcoming_status = null)
|
||||
{
|
||||
|
||||
$filter_non_deprecable_assets = false;
|
||||
|
@ -155,17 +155,44 @@ class AssetsController extends Controller
|
|||
$assets->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
// This is used by the audit reporting routes
|
||||
if (Gate::allows('audit', Asset::class)) {
|
||||
switch ($audit) {
|
||||
case 'due':
|
||||
$assets->DueOrOverdueForAudit($settings);
|
||||
break;
|
||||
case 'overdue':
|
||||
$assets->overdueForAudit($settings);
|
||||
break;
|
||||
|
||||
/**
|
||||
* Handle due and overdue audits and checkin dates
|
||||
*/
|
||||
switch ($action) {
|
||||
case 'audits':
|
||||
|
||||
switch ($upcoming_status) {
|
||||
case 'due':
|
||||
$assets->DueForAudit($settings);
|
||||
break;
|
||||
case 'overdue':
|
||||
$assets->OverdueForAudit();
|
||||
break;
|
||||
case 'due-or-overdue':
|
||||
$assets->DueOrOverdueForAudit($settings);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'checkins':
|
||||
switch ($upcoming_status) {
|
||||
case 'due':
|
||||
$assets->DueForCheckin($settings);
|
||||
break;
|
||||
case 'overdue':
|
||||
$assets->OverdueForCheckin();
|
||||
break;
|
||||
case 'due-or-overdue':
|
||||
$assets->DueOrOverdueForCheckin($settings);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* End handling due and overdue audits and checkin dates
|
||||
*/
|
||||
|
||||
|
||||
// This is used by the sidenav, mostly
|
||||
|
|
|
@ -854,11 +854,11 @@ class AssetsController extends Controller
|
|||
return view('hardware/audit-due');
|
||||
}
|
||||
|
||||
public function overdueForAudit()
|
||||
public function dueForCheckin()
|
||||
{
|
||||
$this->authorize('audit', Asset::class);
|
||||
$this->authorize('checkin', Asset::class);
|
||||
|
||||
return view('hardware/audit-overdue');
|
||||
return view('hardware/checkin-due');
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace App\Http\Middleware;
|
|||
use App\Models\Asset;
|
||||
use Auth;
|
||||
use Closure;
|
||||
use App\Models\Setting;
|
||||
|
||||
class AssetCountForSidebar
|
||||
{
|
||||
|
@ -24,6 +25,13 @@ class AssetCountForSidebar
|
|||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$total_assets = Asset::RTD()->count();
|
||||
view()->share('total_assets', $total_assets);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$total_deployed_sidebar = Asset::Deployed()->count();
|
||||
view()->share('total_deployed_sidebar', $total_deployed_sidebar);
|
||||
|
@ -59,6 +67,44 @@ class AssetCountForSidebar
|
|||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$settings = Setting::getSettings();
|
||||
view()->share('settings', $settings);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$total_due_for_audit = Asset::DueForAudit($settings)->count();
|
||||
view()->share('total_due_for_audit', $total_due_for_audit);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$total_overdue_for_audit = Asset::OverdueForAudit()->count();
|
||||
view()->share('total_overdue_for_audit', $total_overdue_for_audit);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$total_due_for_checkin = Asset::DueForCheckin($settings)->count();
|
||||
view()->share('total_due_for_checkin', $total_due_for_checkin);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$total_overdue_for_checkin = Asset::OverdueForCheckin()->count();
|
||||
view()->share('total_overdue_for_checkin', $total_overdue_for_checkin);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
view()->share('total_due_and_overdue_for_checkin', ($total_due_for_checkin + $total_overdue_for_checkin));
|
||||
view()->share('total_due_and_overdue_for_audit', ($total_due_for_audit + $total_overdue_for_audit));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Http\Requests;
|
|||
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\Setting;
|
||||
use Carbon\Carbon;
|
||||
use Carbon\Exceptions\InvalidFormatException;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
@ -45,12 +46,21 @@ class StoreAssetRequest extends ImageUploadRequest
|
|||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = array_merge(
|
||||
(new Asset)->getRules(),
|
||||
$modelRules = (new Asset)->getRules();
|
||||
|
||||
if (Setting::getSettings()->digit_separator === '1.234,56' && is_string($this->input('purchase_cost'))) {
|
||||
// If purchase_cost was submitted as a string with a comma separator
|
||||
// then we need to ignore the normal numeric rules.
|
||||
// Since the original rules still live on the model they will be run
|
||||
// right before saving (and after purchase_cost has been
|
||||
// converted to a float via setPurchaseCostAttribute).
|
||||
$modelRules = $this->removeNumericRulesFromPurchaseCost($modelRules);
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
$modelRules,
|
||||
parent::rules(),
|
||||
);
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
private function parseLastAuditDate(): void
|
||||
|
@ -69,4 +79,20 @@ class StoreAssetRequest extends ImageUploadRequest
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function removeNumericRulesFromPurchaseCost(array $rules): array
|
||||
{
|
||||
$purchaseCost = $rules['purchase_cost'];
|
||||
|
||||
// If rule is in "|" format then turn it into an array
|
||||
if (is_string($purchaseCost)) {
|
||||
$purchaseCost = explode('|', $purchaseCost);
|
||||
}
|
||||
|
||||
$rules['purchase_cost'] = array_filter($purchaseCost, function ($rule) {
|
||||
return $rule !== 'numeric' && $rule !== 'gte:0';
|
||||
});
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,9 +74,9 @@ class Asset extends Depreciable
|
|||
'eol_explicit' => 'boolean',
|
||||
'last_checkout' => 'datetime',
|
||||
'last_checkin' => 'datetime',
|
||||
'expected_checkin' => 'date',
|
||||
'expected_checkin' => 'datetime:m-d-Y',
|
||||
'last_audit_date' => 'datetime',
|
||||
'next_audit_date' => 'date',
|
||||
'next_audit_date' => 'datetime:m-d-Y',
|
||||
'model_id' => 'integer',
|
||||
'status_id' => 'integer',
|
||||
'company_id' => 'integer',
|
||||
|
@ -1163,10 +1163,11 @@ class Asset extends Depreciable
|
|||
public function scopeDueForAudit($query, $settings)
|
||||
{
|
||||
$interval = $settings->audit_warning_days ?? 0;
|
||||
$today = Carbon::now();
|
||||
$interval_date = $today->copy()->addDays($interval)->format('Y-m-d');
|
||||
|
||||
return $query->whereNotNull('assets.next_audit_date')
|
||||
->where('assets.next_audit_date', '>=', Carbon::now())
|
||||
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'")
|
||||
->whereBetween('assets.next_audit_date', [$today->format('Y-m-d'), $interval_date])
|
||||
->where('assets.archived', '=', 0)
|
||||
->NotArchived();
|
||||
}
|
||||
|
@ -1188,7 +1189,7 @@ class Asset extends Depreciable
|
|||
public function scopeOverdueForAudit($query)
|
||||
{
|
||||
return $query->whereNotNull('assets.next_audit_date')
|
||||
->where('assets.next_audit_date', '<', Carbon::now())
|
||||
->where('assets.next_audit_date', '<', Carbon::now()->format('Y-m-d'))
|
||||
->where('assets.archived', '=', 0)
|
||||
->NotArchived();
|
||||
}
|
||||
|
@ -1209,14 +1210,69 @@ class Asset extends Depreciable
|
|||
|
||||
public function scopeDueOrOverdueForAudit($query, $settings)
|
||||
{
|
||||
$interval = $settings->audit_warning_days ?? 0;
|
||||
|
||||
return $query->whereNotNull('assets.next_audit_date')
|
||||
->whereRaw('DATE_SUB('.DB::getTablePrefix()."assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'")
|
||||
return $query->where(function ($query) {
|
||||
$query->OverdueForAudit();
|
||||
})->orWhere(function ($query) use ($settings) {
|
||||
$query->DueForAudit($settings);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope for Assets that are DUE for checkin, based on the assets.expected_checkin
|
||||
* and settings.audit_warning_days. It checks to see if assets.expected_checkin is now
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since v6.4.0
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeDueForCheckin($query, $settings)
|
||||
{
|
||||
$interval = $settings->audit_warning_days ?? 0;
|
||||
$today = Carbon::now();
|
||||
$interval_date = $today->copy()->addDays($interval)->format('Y-m-d');
|
||||
|
||||
return $query->whereNotNull('assets.expected_checkin')
|
||||
->whereBetween('assets.expected_checkin', [$today->format('Y-m-d'), $interval_date])
|
||||
->where('assets.archived', '=', 0)
|
||||
->whereNotNull('assets.assigned_to')
|
||||
->NotArchived();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope for Assets that are overdue for checkin OR overdue
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since v6.4.0
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOverdueForCheckin($query)
|
||||
{
|
||||
return $query->whereNotNull('assets.expected_checkin')
|
||||
->where('assets.expected_checkin', '<', Carbon::now()->format('Y-m-d'))
|
||||
->where('assets.archived', '=', 0)
|
||||
->whereNotNull('assets.assigned_to')
|
||||
->NotArchived();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope for Assets that are due for checkin OR overdue
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since v6.4.0
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeDueOrOverdueForCheckin($query, $settings)
|
||||
{
|
||||
return $query->where(function ($query) {
|
||||
$query->OverdueForCheckin();
|
||||
})->orWhere(function ($query) use ($settings) {
|
||||
$query->DueForCheckin($settings);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope for Archived assets counting
|
||||
|
|
19
app/Models/Labels/Tapes/Brother/TZe_18mm.php
Normal file
19
app/Models/Labels/Tapes/Brother/TZe_18mm.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Labels\Tapes\Brother;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Labels\Label;
|
||||
|
||||
abstract class TZe_18mm extends Label
|
||||
{
|
||||
private const HEIGHT = 18.00;
|
||||
private const MARGIN_SIDES = 3.20;
|
||||
private const MARGIN_ENDS = 3.20;
|
||||
|
||||
public function getHeight() { return Helper::convertUnit(self::HEIGHT, 'mm', $this->getUnit()); }
|
||||
public function getMarginTop() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit()); }
|
||||
public function getMarginBottom() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());}
|
||||
public function getMarginLeft() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
|
||||
public function getMarginRight() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
|
||||
}
|
56
app/Models/Labels/Tapes/Brother/TZe_18mm_A.php
Normal file
56
app/Models/Labels/Tapes/Brother/TZe_18mm_A.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Labels\Tapes\Brother;
|
||||
|
||||
class TZe_18mm_A extends TZe_18mm
|
||||
{
|
||||
private const BARCODE_SIZE = 3.20;
|
||||
private const BARCODE_MARGIN = 0.30;
|
||||
private const TEXT_SIZE_MOD = 1.00;
|
||||
|
||||
public function getUnit() { return 'mm'; }
|
||||
public function getWidth() { return 50.0; }
|
||||
public function getSupportAssetTag() { return true; }
|
||||
public function getSupport1DBarcode() { return true; }
|
||||
public function getSupport2DBarcode() { return false; }
|
||||
public function getSupportFields() { return 1; }
|
||||
public function getSupportLogo() { return false; }
|
||||
public function getSupportTitle() { return false; }
|
||||
|
||||
public function preparePDF($pdf) {}
|
||||
|
||||
public function write($pdf, $record) {
|
||||
$pa = $this->getPrintableArea();
|
||||
|
||||
if ($record->has('barcode1d')) {
|
||||
static::write1DBarcode(
|
||||
$pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type,
|
||||
$pa->x1, $pa->y1, $pa->w, self::BARCODE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
$currentY = $pa->y1 + self::BARCODE_SIZE + self::BARCODE_MARGIN;
|
||||
$usableHeight = $pa->h - self::BARCODE_SIZE - self::BARCODE_MARGIN;
|
||||
$fontSize = $usableHeight + self::TEXT_SIZE_MOD;
|
||||
|
||||
$tagWidth = $pa->w / 3;
|
||||
$fieldWidth = $pa->w / 3 * 2;
|
||||
|
||||
static::writeText(
|
||||
$pdf, $record->get('tag'),
|
||||
$pa->x1, $currentY,
|
||||
'freemono', 'b', $fontSize, 'L',
|
||||
$tagWidth, $usableHeight, true, 0, 0
|
||||
);
|
||||
|
||||
if ($record->get('fields')->count() >= 1) {
|
||||
static::writeText(
|
||||
$pdf, $record->get('fields')->values()->get(0)['value'],
|
||||
$pa->x1 + ($tagWidth), $currentY,
|
||||
'freemono', 'b', $fontSize, 'R',
|
||||
$fieldWidth, $usableHeight, true, 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
12
composer.lock
generated
12
composer.lock
generated
|
@ -11010,16 +11010,16 @@
|
|||
},
|
||||
{
|
||||
"name": "tecnickcom/tcpdf",
|
||||
"version": "6.7.4",
|
||||
"version": "6.7.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tecnickcom/TCPDF.git",
|
||||
"reference": "d4adef47ca21c90e6483d59dcb9e5b1023696937"
|
||||
"reference": "951eabf0338ec2522bd0d5d9c79b08a3a3d36b36"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/d4adef47ca21c90e6483d59dcb9e5b1023696937",
|
||||
"reference": "d4adef47ca21c90e6483d59dcb9e5b1023696937",
|
||||
"url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/951eabf0338ec2522bd0d5d9c79b08a3a3d36b36",
|
||||
"reference": "951eabf0338ec2522bd0d5d9c79b08a3a3d36b36",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -11070,7 +11070,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/tecnickcom/TCPDF/issues",
|
||||
"source": "https://github.com/tecnickcom/TCPDF/tree/6.7.4"
|
||||
"source": "https://github.com/tecnickcom/TCPDF/tree/6.7.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -11078,7 +11078,7 @@
|
|||
"type": "custom"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-25T23:56:24+00:00"
|
||||
"time": "2024-04-20T17:25:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tijsverkoyen/css-to-inline-styles",
|
||||
|
|
2793
package-lock.json
generated
2793
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -25,7 +25,7 @@
|
|||
"postcss": "^8.4.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.5.0",
|
||||
"@fortawesome/fontawesome-free": "^6.5.2",
|
||||
"acorn": "^8.11.2",
|
||||
"acorn-import-assertions": "^1.9.0",
|
||||
"admin-lte": "^2.4.18",
|
||||
|
@ -55,7 +55,7 @@
|
|||
"select2": "4.0.13",
|
||||
"sheetjs": "^2.0.0",
|
||||
"signature_pad": "^4.2.0",
|
||||
"tableexport.jquery.plugin": "1.28.0",
|
||||
"tableexport.jquery.plugin": "1.30.0",
|
||||
"tether": "^1.4.0",
|
||||
"webpack": "^5.90.2"
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
BIN
public/css/dist/all.css
vendored
BIN
public/css/dist/all.css
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/js/dist/bootstrap-table.js
vendored
BIN
public/js/dist/bootstrap-table.js
vendored
Binary file not shown.
|
@ -1,52 +1,52 @@
|
|||
{
|
||||
"/js/build/app.js": "/js/build/app.js?id=a05df3d0d95cb1cb86b26e858563009f",
|
||||
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=fbe33c09aabd4c4441bd0c7df51dae27",
|
||||
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=81c1f603db10885e65c582b6a4d9990a",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=33450d0bef7d27f0f626ba360088c00c",
|
||||
"/css/build/app.css": "/css/build/app.css?id=2b8033f07b6bddad5ab3c2cf944e2092",
|
||||
"/js/build/app.js": "/js/build/app.js?id=ceb28a75cb946bd1ca5b42002e222142",
|
||||
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=b9a74ec0cd68f83e7480d5ae39919beb",
|
||||
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=392cc93cfc0be0349bab9697669dd091",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=59b5942be1960a787f9d1bb58e7dc068",
|
||||
"/css/build/app.css": "/css/build/app.css?id=bd609c74fd0071b6f93af1869e9482b6",
|
||||
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=a67bd93bed52e6a29967fe472de66d6c",
|
||||
"/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=ff8ee9591f9689de2ceff34df3abf693",
|
||||
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=e1a8f357e3f9f2fe2ca3aa73028d7660",
|
||||
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=ac9d06b3a2273c86e96f3d518556dcc6",
|
||||
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=9d579e001f4d9f61a63c801ee2da1570",
|
||||
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=eaa06b4be5365eeb47df9d78dc8d3f7b",
|
||||
"/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=9dc2632270ea725008c979ba0c3e5e6e",
|
||||
"/css/dist/skins/skin-purple.css": "/css/dist/skins/skin-purple.css?id=51e57ecb88994262fd444f8805ef8dc5",
|
||||
"/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=164148ec02f4c537f70cc1390ea35fca",
|
||||
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=f67a07ab14cd87fe782aa8b1558dbe51",
|
||||
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=875c9e6fdb26015a4eaad7c34abeba3d",
|
||||
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=a9cf77c9b9a7b1c9be035df00294d453",
|
||||
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=2c79e570b79bae4d510cce7e99032359",
|
||||
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=dc03c84f501f028349540a19cff67ac5",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=d950c2d932c847f4dd554dc14fb87957",
|
||||
"/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=268041e902b019730c23ee3875838005",
|
||||
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=03075904b967308132b810bc0205ab1c",
|
||||
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=47ab28abd019c2b1f9aae60a3d44824a",
|
||||
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=af8c7daf7e9a2c784eafb76f65c418f7",
|
||||
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=fc7adb943668ac69fe4b646625a7571f",
|
||||
"/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=7fb8cf2421ad272b41393fdf5844559f",
|
||||
"/css/dist/skins/skin-purple.css": "/css/dist/skins/skin-purple.css?id=cf6c8c340420724b02d6e787ef9bded5",
|
||||
"/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=122d3df19d2c0552d7ef388e69f7d71f",
|
||||
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=5414c37b1403f41e051ad7b3aac112b4",
|
||||
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=1f33ca3d860461c1127ec465ab3ebb6b",
|
||||
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=bd61fefb56b30ed6d8c946f02bc956fb",
|
||||
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=b48f4d8af0e1ca5621c161e93951109f",
|
||||
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=f0fbbb0ac729ea092578fb05ca615460",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=90098fdcbf06c943723c1857f7c31d5d",
|
||||
"/css/dist/signature-pad.css": "/css/dist/signature-pad.css?id=6a89d3cd901305e66ced1cf5f13147f7",
|
||||
"/css/dist/signature-pad.min.css": "/css/dist/signature-pad.min.css?id=6a89d3cd901305e66ced1cf5f13147f7",
|
||||
"/css/webfonts/fa-brands-400.ttf": "/css/webfonts/fa-brands-400.ttf?id=69e5d8e4e818f05fd882cceb758d1eba",
|
||||
"/css/webfonts/fa-brands-400.woff2": "/css/webfonts/fa-brands-400.woff2?id=189b85e9c72c6f75e464c3f58a6707cf",
|
||||
"/css/webfonts/fa-regular-400.ttf": "/css/webfonts/fa-regular-400.ttf?id=ed4c23399d1013809882e90bfe396d1b",
|
||||
"/css/webfonts/fa-regular-400.woff2": "/css/webfonts/fa-regular-400.woff2?id=be75b1958ae0da55e1eed562d9b7713d",
|
||||
"/css/webfonts/fa-solid-900.ttf": "/css/webfonts/fa-solid-900.ttf?id=dfdc7801582dd0d20ea75faa3b96c296",
|
||||
"/css/webfonts/fa-solid-900.woff2": "/css/webfonts/fa-solid-900.woff2?id=a0feb384c3c6071947a49708f2b0bc85",
|
||||
"/css/webfonts/fa-v4compatibility.ttf": "/css/webfonts/fa-v4compatibility.ttf?id=e24ec0b8661f7fa333b29444df39e399",
|
||||
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=e11465c0eff0549edd4e8ea6bbcf242f",
|
||||
"/css/webfonts/fa-brands-400.ttf": "/css/webfonts/fa-brands-400.ttf?id=0141634c24336be626e05c8b77d1fa27",
|
||||
"/css/webfonts/fa-brands-400.woff2": "/css/webfonts/fa-brands-400.woff2?id=b3cf7a6dd618bd392f3ddcc61343a463",
|
||||
"/css/webfonts/fa-regular-400.ttf": "/css/webfonts/fa-regular-400.ttf?id=9cf69d99de9d83f82466a647f5cb1f94",
|
||||
"/css/webfonts/fa-regular-400.woff2": "/css/webfonts/fa-regular-400.woff2?id=f0549181a126fe40849a53792bb0e077",
|
||||
"/css/webfonts/fa-solid-900.ttf": "/css/webfonts/fa-solid-900.ttf?id=509c0e46de844df754d10179cf03c953",
|
||||
"/css/webfonts/fa-solid-900.woff2": "/css/webfonts/fa-solid-900.woff2?id=96d16b1bdb177fd796c810b9e706c780",
|
||||
"/css/webfonts/fa-v4compatibility.ttf": "/css/webfonts/fa-v4compatibility.ttf?id=8994b282f9f3b7a00380bb1e2731a4bf",
|
||||
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=111e341dba724e1df946e8d1f406a7bd",
|
||||
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=99c395f0bab5966f32f63f4e55899e64",
|
||||
"/js/build/vendor.js": "/js/build/vendor.js?id=db2e005808d5a2d2e7f4a82059e5d16f",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=857da5daffd13e0553510e5ccd410c79",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=5f4bdd1b17a98eb4b59085823cf63972",
|
||||
"/js/build/vendor.js": "/js/build/vendor.js?id=179bfe20e8767f7df32658c6b5a10ca3",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=e3bde6c62806c5ae510c964de17cd610",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=99df559d106d7c1da6beff663646d76f",
|
||||
"/js/dist/all-defer.js": "/js/dist/all-defer.js?id=19ccc62a8f1ea103dede4808837384d4",
|
||||
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=2c79e570b79bae4d510cce7e99032359",
|
||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=a9cf77c9b9a7b1c9be035df00294d453",
|
||||
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=875c9e6fdb26015a4eaad7c34abeba3d",
|
||||
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=f67a07ab14cd87fe782aa8b1558dbe51",
|
||||
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=81c1f603db10885e65c582b6a4d9990a",
|
||||
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=ac9d06b3a2273c86e96f3d518556dcc6",
|
||||
"/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=eaa06b4be5365eeb47df9d78dc8d3f7b",
|
||||
"/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=9d579e001f4d9f61a63c801ee2da1570",
|
||||
"/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=fbe33c09aabd4c4441bd0c7df51dae27",
|
||||
"/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=164148ec02f4c537f70cc1390ea35fca",
|
||||
"/css/dist/skins/skin-purple.min.css": "/css/dist/skins/skin-purple.min.css?id=51e57ecb88994262fd444f8805ef8dc5",
|
||||
"/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=9dc2632270ea725008c979ba0c3e5e6e",
|
||||
"/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=ff8ee9591f9689de2ceff34df3abf693",
|
||||
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=e1a8f357e3f9f2fe2ca3aa73028d7660",
|
||||
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=dc03c84f501f028349540a19cff67ac5"
|
||||
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=b48f4d8af0e1ca5621c161e93951109f",
|
||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=bd61fefb56b30ed6d8c946f02bc956fb",
|
||||
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=1f33ca3d860461c1127ec465ab3ebb6b",
|
||||
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=5414c37b1403f41e051ad7b3aac112b4",
|
||||
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=392cc93cfc0be0349bab9697669dd091",
|
||||
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=47ab28abd019c2b1f9aae60a3d44824a",
|
||||
"/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=fc7adb943668ac69fe4b646625a7571f",
|
||||
"/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=af8c7daf7e9a2c784eafb76f65c418f7",
|
||||
"/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=b9a74ec0cd68f83e7480d5ae39919beb",
|
||||
"/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=122d3df19d2c0552d7ef388e69f7d71f",
|
||||
"/css/dist/skins/skin-purple.min.css": "/css/dist/skins/skin-purple.min.css?id=cf6c8c340420724b02d6e787ef9bded5",
|
||||
"/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=7fb8cf2421ad272b41393fdf5844559f",
|
||||
"/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=268041e902b019730c23ee3875838005",
|
||||
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=03075904b967308132b810bc0205ab1c",
|
||||
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=f0fbbb0ac729ea092578fb05ca615460"
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
//Hover and active states
|
||||
&:hover > a, &.active > a {
|
||||
color: @sidebar-dark-hover-color;
|
||||
background: @link-hover-border-color;
|
||||
background: @sidebar-dark-hover-bg;
|
||||
border-left-color: @link-hover-border-color;
|
||||
}
|
||||
//First Level Submenu
|
||||
|
|
|
@ -900,4 +900,10 @@ input[type="radio"]:checked::before {
|
|||
}
|
||||
.datepicker.dropdown-menu {
|
||||
z-index: 1030 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-menu > li .badge {
|
||||
margin-top: 0px;
|
||||
filter: brightness(70%);
|
||||
font-size: 70%;
|
||||
}
|
||||
|
|
|
@ -313,6 +313,10 @@ return [
|
|||
'token_expired' => 'Your form session has expired. Please try again.',
|
||||
'login_enabled' => 'Login Enabled',
|
||||
'audit_due' => 'Due for Audit',
|
||||
'audit_due_days' => 'Assets Due for Audit Within :days Day|Assets Due for Audit Within :days Days',
|
||||
'checkin_due' => 'Due for Checkin',
|
||||
'checkin_overdue' => 'Overdue for Checkin',
|
||||
'checkin_due_days' => 'Assets Due for Checkin Within :days Day|Assets Due for Checkin Within :days Days',
|
||||
'audit_overdue' => 'Overdue for Audit',
|
||||
'accept' => 'Accept :asset',
|
||||
'i_accept' => 'I accept',
|
||||
|
|
|
@ -1,40 +1,59 @@
|
|||
@extends('layouts/default')
|
||||
|
||||
@section('title0')
|
||||
|
||||
@if ((Request::get('company_id')) && ($company))
|
||||
{{ $company->name }}
|
||||
@endif
|
||||
|
||||
{{ trans('general.audit_due') }}
|
||||
|
||||
@stop
|
||||
|
||||
{{-- Page title --}}
|
||||
@section('title')
|
||||
@yield('title0') @parent
|
||||
{{ trans_choice('general.audit_due_days', $settings->audit_warning_days, ['days' => $settings->audit_warning_days]) }}
|
||||
@stop
|
||||
|
||||
|
||||
|
||||
{{-- Page content --}}
|
||||
@section('content')
|
||||
|
||||
{{-- Page content --}}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box">
|
||||
<div class="box-body">
|
||||
|
||||
@include('partials.asset-bulk-actions')
|
||||
<!-- Custom Tabs -->
|
||||
<div class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs hidden-print">
|
||||
|
||||
<li class="active">
|
||||
<a href="#due" data-toggle="tab">{{ trans('general.audit_due') }}
|
||||
<span class="hidden-lg hidden-md">
|
||||
<i class="far fa-file fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="badge">{{ (isset($total_due_for_audit)) ? $total_due_for_audit : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#overdue" data-toggle="tab">{{ trans('general.audit_overdue') }}
|
||||
<span class="hidden-lg hidden-md">
|
||||
<i class="far fa-file fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="badge">{{ (isset($total_overdue_for_audit)) ? $total_overdue_for_audit : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane active" id="due">
|
||||
|
||||
@include('partials.asset-bulk-actions',
|
||||
[
|
||||
'id_divname' => 'dueAssetEditToolbar',
|
||||
'id_formname' => 'dueAssetEditForm',
|
||||
'id_button' => 'dueAssetEditButton'])
|
||||
|
||||
<div class="row">
|
||||
<div class="table table-responsive">
|
||||
<div class="col-md-12">
|
||||
|
||||
<table
|
||||
data-click-to-select="true"
|
||||
data-columns="{{ \App\Presenters\AssetAuditPresenter::dataTableLayout() }}"
|
||||
data-cookie-id-table="assetsAuditListingTable"
|
||||
data-cookie-id-table="dueAssetAuditListing"
|
||||
data-pagination="true"
|
||||
data-id-table="assetsAuditListingTable"
|
||||
data-id-table="dueAssetAuditListing"
|
||||
data-search="true"
|
||||
data-side-pagination="server"
|
||||
data-show-columns="true"
|
||||
|
@ -44,28 +63,71 @@
|
|||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
data-toolbar="#assetsBulkEditToolbar"
|
||||
data-bulk-button-id="#bulkAssetEditButton"
|
||||
data-bulk-form-id="#assetsBulkForm"
|
||||
id="assetsAuditListingTable"
|
||||
data-toolbar="#dueAssetEditToolbar"
|
||||
data-bulk-button-id="#dueAssetEditButton"
|
||||
data-bulk-form-id="#dueAssetEditForm"
|
||||
id="#dueAssetAuditListing"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.asset.to-audit', ['audit' => 'due']) }}"
|
||||
data-url="{{ route('api.assets.list-upcoming', ['action' => 'audits', 'upcoming_status' => 'due']) }}"
|
||||
data-export-options='{
|
||||
"fileName": "export-assets-due-audit-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
}'>
|
||||
</table>
|
||||
</div> <!-- end col-md-12 -->
|
||||
</div><!-- end table-responsive -->
|
||||
</div><!-- end row -->
|
||||
</div><!-- end tab-pane -->
|
||||
|
||||
<div class="tab-pane" id="overdue">
|
||||
|
||||
@include('partials.asset-bulk-actions',
|
||||
[
|
||||
'id_divname' => 'overdueAssetEditToolbar',
|
||||
'id_formname' => 'overdueAssetEditForm',
|
||||
'id_button' => 'overdueAssetEditButton'])
|
||||
|
||||
<div class="row">
|
||||
<div class="table table-responsive">
|
||||
<div class="col-md-12">
|
||||
<table
|
||||
data-click-to-select="true"
|
||||
data-columns="{{ \App\Presenters\AssetAuditPresenter::dataTableLayout() }}"
|
||||
data-cookie-id-table="overdueAssetAuditListing"
|
||||
data-pagination="true"
|
||||
data-id-table="overdueAssetAuditListing"
|
||||
data-search="true"
|
||||
data-side-pagination="server"
|
||||
data-show-columns="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
data-toolbar="#overdueAssetEditToolbar"
|
||||
data-bulk-button-id="#overdueAssetEditButton"
|
||||
data-bulk-form-id="#overdueAssetEditForm"
|
||||
id="#overdueAssetAuditListing"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.assets.list-upcoming', ['action' => 'audits', 'upcoming_status' => 'overdue']) }}"
|
||||
data-export-options='{
|
||||
"fileName": "export-assets-overdue-audit-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
}'>
|
||||
</table>
|
||||
</div> <!-- end col-md-12 -->
|
||||
</div><!-- end table-responsive -->
|
||||
</div><!-- end row -->
|
||||
</div><!-- end tab-pane -->
|
||||
</div><!-- end tab-content -->
|
||||
</div><!-- end nav-tabs-custom -->
|
||||
|
||||
</div><!-- /.col -->
|
||||
</div><!-- /.row -->
|
||||
{{ Form::close() }}
|
||||
</div><!-- ./box-body -->
|
||||
</div><!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@stop
|
||||
|
||||
@section('moar_scripts')
|
||||
@include('partials.bootstrap-table')
|
||||
|
||||
@stop
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
@extends('layouts/default')
|
||||
|
||||
@section('title0')
|
||||
|
||||
@if ((Request::get('company_id')) && ($company))
|
||||
{{ $company->name }}
|
||||
@endif
|
||||
|
||||
{{ trans('general.audit_overdue') }}
|
||||
|
||||
@stop
|
||||
|
||||
{{-- Page title --}}
|
||||
@section('title')
|
||||
@yield('title0') @parent
|
||||
@stop
|
||||
|
||||
|
||||
{{-- Page content --}}
|
||||
@section('content')
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box">
|
||||
<div class="box-body">
|
||||
@include('partials.asset-bulk-actions')
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<table
|
||||
data-click-to-select="true"
|
||||
data-columns="{{ \App\Presenters\AssetAuditPresenter::dataTableLayout() }}"
|
||||
data-cookie-id-table="assetsOverdueAuditListingTable"
|
||||
data-pagination="true"
|
||||
data-id-table="assetsOverdueAuditListingTable"
|
||||
data-search="true"
|
||||
data-side-pagination="server"
|
||||
data-show-columns="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
data-toolbar="#assetsBulkEditToolbar"
|
||||
data-bulk-button-id="#bulkAssetEditButton"
|
||||
data-bulk-form-id="#assetsBulkForm"
|
||||
id="assetsAuditListingTable"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.asset.to-audit', ['audit' => 'overdue']) }}"
|
||||
data-export-options='{
|
||||
"fileName": "export-assets-due-audit-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
}'>
|
||||
</table>
|
||||
|
||||
</div><!-- /.col -->
|
||||
</div><!-- /.row -->
|
||||
{{ Form::close() }}
|
||||
</div><!-- ./box-body -->
|
||||
</div><!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
||||
@section('moar_scripts')
|
||||
@include('partials.bootstrap-table')
|
||||
|
||||
@stop
|
131
resources/views/hardware/checkin-due.blade.php
Normal file
131
resources/views/hardware/checkin-due.blade.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
@extends('layouts/default')
|
||||
|
||||
{{-- Page title --}}
|
||||
@section('title')
|
||||
{{ trans_choice('general.checkin_due_days', $settings->audit_warning_days, ['days' => $settings->audit_warning_days]) }}
|
||||
@stop
|
||||
|
||||
{{-- Page content --}}
|
||||
@section('content')
|
||||
{{-- Page content --}}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<!-- Custom Tabs -->
|
||||
<div class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs hidden-print">
|
||||
|
||||
<li class="active">
|
||||
<a href="#due" data-toggle="tab">{{ trans('general.checkin_due') }}
|
||||
<span class="hidden-lg hidden-md">
|
||||
<i class="far fa-file fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="badge">{{ (isset($total_due_for_checkin)) ? $total_due_for_checkin : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#overdue" data-toggle="tab">{{ trans('general.checkin_overdue') }}
|
||||
<span class="hidden-lg hidden-md">
|
||||
<i class="far fa-file fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="badge">{{ (isset($total_overdue_for_checkin)) ? $total_overdue_for_checkin : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane active" id="due">
|
||||
|
||||
@include('partials.asset-bulk-actions',
|
||||
[
|
||||
'id_divname' => 'dueAssetEditToolbar',
|
||||
'id_formname' => 'dueAssetEditForm',
|
||||
'id_button' => 'dueAssetEditButton'])
|
||||
|
||||
<div class="row">
|
||||
<div class="table table-responsive">
|
||||
<div class="col-md-12">
|
||||
<table
|
||||
data-click-to-select="true"
|
||||
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
|
||||
data-cookie-id-table="dueAssetcheckinListing"
|
||||
data-pagination="true"
|
||||
data-id-table="dueAssetcheckinListing"
|
||||
data-search="true"
|
||||
data-side-pagination="server"
|
||||
data-show-columns="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
data-toolbar="#dueAssetEditToolbar"
|
||||
data-bulk-button-id="#dueAssetEditButton"
|
||||
data-bulk-form-id="#dueAssetEditForm"
|
||||
id="#dueAssetcheckinListing"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.assets.list-upcoming', ['action' => 'checkins', 'upcoming_status' => 'due']) }}"
|
||||
data-export-options='{
|
||||
"fileName": "export-assets-due-checkin-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
}'>
|
||||
</table>
|
||||
</div> <!-- end col-md-12 -->
|
||||
</div><!-- end table-responsive -->
|
||||
</div><!-- end row -->
|
||||
</div><!-- end tab-pane -->
|
||||
|
||||
<div class="tab-pane" id="overdue">
|
||||
|
||||
@include('partials.asset-bulk-actions',
|
||||
[
|
||||
'id_divname' => 'overdueAssetEditToolbar',
|
||||
'id_formname' => 'overdueAssetEditForm',
|
||||
'id_button' => 'overdueAssetEditButton'])
|
||||
|
||||
<div class="row">
|
||||
<div class="table table-responsive">
|
||||
<div class="col-md-12">
|
||||
<table
|
||||
data-click-to-select="true"
|
||||
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
|
||||
data-cookie-id-table="overdueAssetcheckinListing"
|
||||
data-pagination="true"
|
||||
data-id-table="overdueAssetcheckinListing"
|
||||
data-search="true"
|
||||
data-side-pagination="server"
|
||||
data-show-columns="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
data-toolbar="#overdueAssetEditToolbar"
|
||||
data-bulk-button-id="#overdueAssetEditButton"
|
||||
data-bulk-form-id="#overdueAssetEditForm"
|
||||
id="#overdueAssetcheckinListing"
|
||||
class="table table-striped snipe-table"
|
||||
data-url="{{ route('api.assets.list-upcoming', ['action' => 'checkins', 'upcoming_status' => 'overdue']) }}"
|
||||
data-export-options='{
|
||||
"fileName": "export-assets-overdue-checkin-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
}'>
|
||||
</table>
|
||||
</div> <!-- end col-md-12 -->
|
||||
</div><!-- end table-responsive -->
|
||||
</div><!-- end row -->
|
||||
</div><!-- end tab-pane -->
|
||||
</div><!-- end tab-content -->
|
||||
</div><!-- end nav-tabs-custom -->
|
||||
|
||||
</div><!-- /.col -->
|
||||
</div><!-- /.row -->
|
||||
|
||||
@stop
|
||||
|
||||
@section('moar_scripts')
|
||||
@include('partials.bootstrap-table')
|
||||
@stop
|
|
@ -51,7 +51,7 @@
|
|||
<i class="far fa-save fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('general.licenses') }}
|
||||
{!! ($asset->licenses->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($asset->licenses->count()).'</badge>' : '' !!}
|
||||
{!! ($asset->licenses->count() > 0 ) ? '<span class="badge badge-secondary">'.number_format($asset->licenses->count()).'</span>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -62,7 +62,7 @@
|
|||
<i class="far fa-hdd fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('general.components') }}
|
||||
{!! ($asset->components->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($asset->components->count()).'</badge>' : '' !!}
|
||||
{!! ($asset->components->count() > 0 ) ? '<span class="badge badge-secondary">'.number_format($asset->components->count()).'</span>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -73,7 +73,7 @@
|
|||
<i class="fas fa-barcode fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('general.assets') }}
|
||||
{!! ($asset->assignedAssets()->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($asset->assignedAssets()->count()).'</badge>' : '' !!}
|
||||
{!! ($asset->assignedAssets()->count() > 0 ) ? '<span class="badge badge-secondary">'.number_format($asset->assignedAssets()->count()).'</span>' : '' !!}
|
||||
|
||||
</span>
|
||||
</a>
|
||||
|
@ -96,7 +96,7 @@
|
|||
<i class="fas fa-wrench fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('general.maintenances') }}
|
||||
{!! ($asset->assetmaintenances()->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($asset->assetmaintenances()->count()).'</badge>' : '' !!}
|
||||
{!! ($asset->assetmaintenances()->count() > 0 ) ? '<span class="badge badge-secondary">'.number_format($asset->assetmaintenances()->count()).'</span>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -107,7 +107,7 @@
|
|||
<i class="far fa-file fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('general.files') }}
|
||||
{!! ($asset->uploads->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($asset->uploads->count()).'</badge>' : '' !!}
|
||||
{!! ($asset->uploads->count() > 0 ) ? '<span class="badge badge-secondary">'.number_format($asset->uploads->count()).'</span>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -119,7 +119,7 @@
|
|||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
{{ trans('general.additional_files') }}
|
||||
{!! ($asset->model) && ($asset->model->uploads->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($asset->model->uploads->count()).'</badge>' : '' !!}
|
||||
{!! ($asset->model) && ($asset->model->uploads->count() > 0 ) ? '<span class="badge badge-secondary">'.number_format($asset->model->uploads->count()).'</span>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"
|
||||
dir="{{ in_array(app()->getLocale(),['ar-SA','fa-IR', 'he-IL']) ? 'rtl' : 'ltr' }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
@ -437,6 +438,9 @@
|
|||
<a href="{{ url('hardware') }}">
|
||||
<i class="far fa-circle text-grey fa-fw" aria-hidden="true"></i>
|
||||
{{ trans('general.list_all') }}
|
||||
<span class="badge">
|
||||
{{ (isset($total_assets)) ? $total_assets : '' }}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
@ -447,7 +451,8 @@
|
|||
<a href="{{ route('statuslabels.show', ['statuslabel' => $status_nav->id]) }}">
|
||||
<i class="fas fa-circle text-grey fa-fw"
|
||||
aria-hidden="true"{!! ($status_nav->color!='' ? ' style="color: '.e($status_nav->color).'"' : '') !!}></i>
|
||||
{{ $status_nav->name }} ({{ $status_nav->asset_count }})</a></li>
|
||||
{{ $status_nav->name }}
|
||||
<span class="badge badge-secondary">{{ $status_nav->asset_count }})</span></a></li>
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
|
@ -455,49 +460,43 @@
|
|||
<li{!! (Request::query('status') == 'Deployed' ? ' class="active"' : '') !!}>
|
||||
<a href="{{ url('hardware?status=Deployed') }}">
|
||||
<i class="far fa-circle text-blue fa-fw"></i>
|
||||
{{ trans('general.all') }}
|
||||
{{ trans('general.deployed') }}
|
||||
({{ (isset($total_deployed_sidebar)) ? $total_deployed_sidebar : '' }})
|
||||
<span class="badge">{{ (isset($total_deployed_sidebar)) ? $total_deployed_sidebar : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li{!! (Request::query('status') == 'RTD' ? ' class="active"' : '') !!}>
|
||||
<a href="{{ url('hardware?status=RTD') }}">
|
||||
<i class="far fa-circle text-green fa-fw"></i>
|
||||
{{ trans('general.all') }}
|
||||
{{ trans('general.ready_to_deploy') }}
|
||||
({{ (isset($total_rtd_sidebar)) ? $total_rtd_sidebar : '' }})
|
||||
<span class="badge">{{ (isset($total_rtd_sidebar)) ? $total_rtd_sidebar : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li{!! (Request::query('status') == 'Pending' ? ' class="active"' : '') !!}><a
|
||||
href="{{ url('hardware?status=Pending') }}"><i
|
||||
class="far fa-circle text-orange fa-fw"></i>
|
||||
{{ trans('general.all') }}
|
||||
{{ trans('general.pending') }}
|
||||
({{ (isset($total_pending_sidebar)) ? $total_pending_sidebar : '' }})
|
||||
<span class="badge">{{ (isset($total_pending_sidebar)) ? $total_pending_sidebar : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li{!! (Request::query('status') == 'Undeployable' ? ' class="active"' : '') !!} ><a
|
||||
href="{{ url('hardware?status=Undeployable') }}"><i
|
||||
class="fas fa-times text-red fa-fw"></i>
|
||||
{{ trans('general.all') }}
|
||||
{{ trans('general.undeployable') }}
|
||||
({{ (isset($total_undeployable_sidebar)) ? $total_undeployable_sidebar : '' }})
|
||||
<span class="badge">{{ (isset($total_undeployable_sidebar)) ? $total_undeployable_sidebar : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li{!! (Request::query('status') == 'byod' ? ' class="active"' : '') !!}><a
|
||||
href="{{ url('hardware?status=byod') }}"><i
|
||||
class="fas fa-times text-red fa-fw"></i>
|
||||
{{ trans('general.all') }}
|
||||
{{ trans('general.byod') }}
|
||||
({{ (isset($total_byod_sidebar)) ? $total_byod_sidebar : '' }})
|
||||
<span class="badge">{{ (isset($total_byod_sidebar)) ? $total_byod_sidebar : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li{!! (Request::query('status') == 'Archived' ? ' class="active"' : '') !!}><a
|
||||
href="{{ url('hardware?status=Archived') }}"><i
|
||||
class="fas fa-times text-red fa-fw"></i>
|
||||
{{ trans('general.all') }}
|
||||
{{ trans('admin/hardware/general.archived') }}
|
||||
({{ (isset($total_archived_sidebar)) ? $total_archived_sidebar : '' }})
|
||||
<span class="badge">{{ (isset($total_archived_sidebar)) ? $total_archived_sidebar : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li{!! (Request::query('status') == 'Requestable' ? ' class="active"' : '') !!}><a
|
||||
|
@ -511,13 +510,18 @@
|
|||
<li{!! (Request::is('hardware/audit/due') ? ' class="active"' : '') !!}>
|
||||
<a href="{{ route('assets.audit.due') }}">
|
||||
<i class="fas fa-history text-yellow fa-fw"></i> {{ trans('general.audit_due') }}
|
||||
<span class="badge">{{ (isset($total_due_and_overdue_for_audit)) ? $total_due_and_overdue_for_audit : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li{!! (Request::is('hardware/audit/overdue') ? ' class="active"' : '') !!}>
|
||||
<a href="{{ route('assets.audit.overdue') }}">
|
||||
<i class="fas fa-exclamation-triangle text-red fa-fw"></i> {{ trans('general.audit_overdue') }}
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
|
||||
@can('checkin', \App\Models\Asset::class)
|
||||
<li{!! (Request::is('hardware/checkins/due') ? ' class="active"' : '') !!}>
|
||||
<a href="{{ route('assets.checkins.due') }}">
|
||||
<i class="fas fa-history text-yellow fa-fw"></i> {{ trans('general.checkin_due') }}
|
||||
<span class="badge">{{ (isset($total_due_and_overdue_for_checkin)) ? $total_due_and_overdue_for_checkin : '' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
|
||||
<li class="divider"> </li>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
@php
|
||||
$checkin = Helper::getFormattedDateObject($asset->expected_checkin, 'date');
|
||||
@endphp
|
||||
| [{{ $asset->present()->name }}]({{ route('hardware.show', ['hardware' => $asset->id]) }}) | [{{ $asset->assigned->present()->fullName }}]({{ route($asset->targetShowRoute().'.show', [$asset->assigned->id]) }}) | {{ $checkin['formatted'] }}
|
||||
| [{{ $asset->present()->name }}]({{ route('hardware.show', ['hardware' => $asset->id]) }}) | [{{ $asset->assignedTo->present()->fullName }}]({{ route($asset->targetShowRoute().'.show', [$asset->assignedTo->id]) }}) | {{ $checkin['formatted'] }}
|
||||
@endforeach
|
||||
@endcomponent
|
||||
|
||||
|
|
|
@ -496,13 +496,27 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:api']], functi
|
|||
)->name('api.assets.show.byserial')
|
||||
->where('any', '.*');
|
||||
|
||||
Route::get('audit/{audit}',
|
||||
// LEGACY URL - Get assets that are due or overdue for audit
|
||||
Route::get('audit/{status}',
|
||||
[
|
||||
Api\AssetsController::class,
|
||||
'index'
|
||||
]
|
||||
)->name('api.asset.to-audit');
|
||||
|
||||
|
||||
|
||||
// This gets the "due or overdue" API endpoints for audits and checkins
|
||||
Route::get('{action}/{upcoming_status}',
|
||||
[
|
||||
Api\AssetsController::class,
|
||||
'index'
|
||||
]
|
||||
)->name('api.assets.list-upcoming')
|
||||
->where(['action' => 'audits|checkins', 'upcoming_status' => 'due|overdue|due-or-overdue']);
|
||||
|
||||
|
||||
|
||||
Route::post('audit',
|
||||
[
|
||||
Api\AssetsController::class,
|
||||
|
|
|
@ -50,26 +50,10 @@ Route::group(
|
|||
[AssetsController::class, 'dueForAudit']
|
||||
)->name('assets.audit.due');
|
||||
|
||||
Route::get('audit/overdue',
|
||||
[AssetsController::class, 'overdueForAudit']
|
||||
)->name('assets.audit.overdue');
|
||||
|
||||
Route::get('audit/due',
|
||||
[AssetsController::class, 'dueForAudit']
|
||||
)->name('assets.audit.due');
|
||||
|
||||
Route::get('audit/overdue',
|
||||
[AssetsController::class, 'overdueForAudit']
|
||||
)->name('assets.audit.overdue');
|
||||
|
||||
Route::get('audit/due',
|
||||
[AssetsController::class, 'dueForAudit']
|
||||
)->name('assets.audit.due');
|
||||
|
||||
Route::get('audit/overdue',
|
||||
[AssetsController::class, 'overdueForAudit']
|
||||
)->name('assets.audit.overdue');
|
||||
|
||||
Route::get('checkins/due',
|
||||
[AssetsController::class, 'dueForCheckin']
|
||||
)->name('assets.checkins.due');
|
||||
|
||||
Route::get('audit/{id}',
|
||||
[AssetsController::class, 'audit']
|
||||
)->name('asset.audit.create');
|
||||
|
|
|
@ -7,10 +7,10 @@ use App\Models\Company;
|
|||
use App\Models\User;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Tests\TestCase;
|
||||
|
||||
use Carbon\Carbon;
|
||||
class AssetIndexTest extends TestCase
|
||||
{
|
||||
public function testAssetIndexReturnsExpectedAssets()
|
||||
public function testAssetApiIndexReturnsExpectedAssets()
|
||||
{
|
||||
Asset::factory()->count(3)->create();
|
||||
|
||||
|
@ -30,7 +30,102 @@ class AssetIndexTest extends TestCase
|
|||
->assertJson(fn(AssertableJson $json) => $json->has('rows', 3)->etc());
|
||||
}
|
||||
|
||||
public function testAssetIndexAdheresToCompanyScoping()
|
||||
public function testAssetApiIndexReturnsDisplayUpcomingAuditsDue()
|
||||
{
|
||||
Asset::factory()->count(3)->create(['next_audit_date' => Carbon::now()->format('Y-m-d')]);
|
||||
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->getJson(
|
||||
route('api.assets.list-upcoming', ['action' => 'audits', 'upcoming_status' => 'due']))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows',
|
||||
])
|
||||
->assertJson(fn(AssertableJson $json) => $json->has('rows', 3)->etc());
|
||||
}
|
||||
|
||||
public function testAssetApiIndexReturnsOverdueForAudit()
|
||||
{
|
||||
Asset::factory()->count(3)->create(['next_audit_date' => Carbon::now()->subDays(1)->format('Y-m-d')]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->getJson(
|
||||
route('api.assets.list-upcoming', ['action' => 'audits', 'upcoming_status' => 'overdue']))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows',
|
||||
])
|
||||
->assertJson(fn(AssertableJson $json) => $json->has('rows', 3)->etc());
|
||||
}
|
||||
|
||||
|
||||
public function testAssetApiIndexReturnsDueOrOverdueForAudit()
|
||||
{
|
||||
Asset::factory()->count(3)->create(['next_audit_date' => Carbon::now()->format('Y-m-d')]);
|
||||
Asset::factory()->count(2)->create(['next_audit_date' => Carbon::now()->subDays(1)->format('Y-m-d')]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->getJson(
|
||||
route('api.assets.list-upcoming', ['action' => 'audits', 'upcoming_status' => 'due-or-overdue']))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows',
|
||||
])
|
||||
->assertJson(fn(AssertableJson $json) => $json->has('rows', 5)->etc());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testAssetApiIndexReturnsDueForExpectedCheckin()
|
||||
{
|
||||
Asset::factory()->count(3)->create(['assigned_to' => '1', 'expected_checkin' => Carbon::now()->format('Y-m-d')]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->getJson(
|
||||
route('api.assets.list-upcoming', ['action' => 'checkins', 'upcoming_status' => 'due'])
|
||||
)
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows',
|
||||
])
|
||||
->assertJson(fn(AssertableJson $json) => $json->has('rows', 3)->etc());
|
||||
}
|
||||
|
||||
public function testAssetApiIndexReturnsOverdueForExpectedCheckin()
|
||||
{
|
||||
Asset::factory()->count(3)->create(['assigned_to' => '1', 'expected_checkin' => Carbon::now()->subDays(1)->format('Y-m-d')]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->getJson(route('api.assets.list-upcoming', ['action' => 'checkins', 'upcoming_status' => 'overdue']))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows',
|
||||
])
|
||||
->assertJson(fn(AssertableJson $json) => $json->has('rows', 3)->etc());
|
||||
}
|
||||
|
||||
public function testAssetApiIndexReturnsDueOrOverdueForExpectedCheckin()
|
||||
{
|
||||
Asset::factory()->count(3)->create(['assigned_to' => '1', 'expected_checkin' => Carbon::now()->subDays(1)->format('Y-m-d')]);
|
||||
Asset::factory()->count(2)->create(['assigned_to' => '1', 'expected_checkin' => Carbon::now()->format('Y-m-d')]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->getJson(route('api.assets.list-upcoming', ['action' => 'checkins', 'upcoming_status' => 'due-or-overdue']))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows',
|
||||
])
|
||||
->assertJson(fn(AssertableJson $json) => $json->has('rows', 5)->etc());
|
||||
}
|
||||
|
||||
public function testAssetApiIndexAdheresToCompanyScoping()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Tests\Feature\Api\Assets;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Company;
|
||||
|
@ -12,6 +13,7 @@ use App\Models\Supplier;
|
|||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Illuminate\Testing\TestResponse;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetStoreTest extends TestCase
|
||||
|
@ -278,6 +280,50 @@ class AssetStoreTest extends TestCase
|
|||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testStoresPeriodAsDecimalSeparatorForPurchaseCost()
|
||||
{
|
||||
$this->settings->set([
|
||||
'default_currency' => 'USD',
|
||||
'digit_separator' => '1,234.56',
|
||||
]);
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'asset_tag' => 'random-string',
|
||||
'model_id' => AssetModel::factory()->create()->id,
|
||||
'status_id' => Statuslabel::factory()->create()->id,
|
||||
// API accepts float
|
||||
'purchase_cost' => 12.34,
|
||||
])
|
||||
->assertStatusMessageIs('success');
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
|
||||
$this->assertEquals(12.34, $asset->purchase_cost);
|
||||
}
|
||||
|
||||
public function testStoresPeriodAsCommaSeparatorForPurchaseCost()
|
||||
{
|
||||
$this->settings->set([
|
||||
'default_currency' => 'EUR',
|
||||
'digit_separator' => '1.234,56',
|
||||
]);
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'asset_tag' => 'random-string',
|
||||
'model_id' => AssetModel::factory()->create()->id,
|
||||
'status_id' => Statuslabel::factory()->create()->id,
|
||||
// API also accepts string for comma separated values
|
||||
'purchase_cost' => '12,34',
|
||||
])
|
||||
->assertStatusMessageIs('success');
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
|
||||
$this->assertEquals(12.34, $asset->purchase_cost);
|
||||
}
|
||||
|
||||
public function testUniqueSerialNumbersIsEnforcedWhenEnabled()
|
||||
{
|
||||
$model = AssetModel::factory()->create();
|
||||
|
|
|
@ -16,4 +16,13 @@ class HelperTest extends TestCase
|
|||
{
|
||||
$this->assertIsString(Helper::defaultChartColors(-1));
|
||||
}
|
||||
|
||||
public function testParseCurrencyMethod()
|
||||
{
|
||||
$this->settings->set(['default_currency' => 'USD']);
|
||||
$this->assertSame(12.34, Helper::ParseCurrency('USD 12.34'));
|
||||
|
||||
$this->settings->set(['digit_separator' => '1.234,56']);
|
||||
$this->assertSame(12.34, Helper::ParseCurrency('12,34'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ if($upgrade_requirements){
|
|||
// done fetching requirements
|
||||
|
||||
if (!$no_interactive) {
|
||||
$yesno = readline("\nProceed with upgrade? [Y/n]: ");
|
||||
$yesno = readline("\nProceed with upgrade? [y/N]: ");
|
||||
} else {
|
||||
$yesno = "yes";
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue