Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net> # Conflicts: # public/css/build/app.css # public/css/build/overrides.css # public/css/dist/all.css # public/mix-manifest.json
This commit is contained in:
commit
1e1782c232
30 changed files with 860 additions and 223 deletions
|
@ -9,7 +9,6 @@ use App\Notifications\ExpectedCheckinAdminNotification;
|
||||||
use App\Notifications\ExpectedCheckinNotification;
|
use App\Notifications\ExpectedCheckinNotification;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
class SendExpectedCheckinAlerts extends Command
|
class SendExpectedCheckinAlerts extends Command
|
||||||
{
|
{
|
||||||
|
@ -43,25 +42,31 @@ class SendExpectedCheckinAlerts extends Command
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$settings = Setting::getSettings();
|
$settings = Setting::getSettings();
|
||||||
$whenNotify = Carbon::now();
|
$interval = $settings->audit_warning_days ?? 0;
|
||||||
$assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
|
$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) {
|
foreach ($assets as $asset) {
|
||||||
if ($asset->assigned && $asset->checkedOutToUser()) {
|
if ($asset->assignedTo && (isset($asset->assignedTo->email)) && ($asset->assignedTo->email!='') && $asset->checkedOutToUser()) {
|
||||||
Log::info('Sending ExpectedCheckinNotification to ' . $asset->assigned->email);
|
$this->info('Sending User ExpectedCheckinNotification to: '.$asset->assignedTo->email);
|
||||||
$asset->assigned->notify((new ExpectedCheckinNotification($asset)));
|
$asset->assignedTo->notify((new ExpectedCheckinNotification($asset)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
||||||
// Send a rollup to the admin, if settings dictate
|
// 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);
|
return new AlertRecipient($item);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$this->info('Sending Admin ExpectedCheckinNotification to: '.$settings->alert_email);
|
||||||
\Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
|
\Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,8 @@
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\License;
|
use App\Models\Recipients\AlertRecipient;
|
||||||
use App\Models\Recipients;
|
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Notifications\ExpiringAssetsNotification;
|
|
||||||
use App\Notifications\SendUpcomingAuditNotification;
|
use App\Notifications\SendUpcomingAuditNotification;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DB;
|
use DB;
|
||||||
|
@ -45,40 +43,26 @@ class SendUpcomingAuditReport extends Command
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
$interval = $settings->audit_warning_days ?? 0;
|
||||||
|
$today = Carbon::now();
|
||||||
|
$interval_date = $today->copy()->addDays($interval);
|
||||||
|
|
||||||
$settings = Setting::getSettings();
|
$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
|
// 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 \App\Models\Recipients\AlertRecipient($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]
|
* @since [v4.0]
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @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;
|
$filter_non_deprecable_assets = false;
|
||||||
|
@ -155,17 +155,44 @@ class AssetsController extends Controller
|
||||||
$assets->TextSearch($request->input('search'));
|
$assets->TextSearch($request->input('search'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used by the audit reporting routes
|
|
||||||
if (Gate::allows('audit', Asset::class)) {
|
/**
|
||||||
switch ($audit) {
|
* Handle due and overdue audits and checkin dates
|
||||||
case 'due':
|
*/
|
||||||
$assets->DueOrOverdueForAudit($settings);
|
switch ($action) {
|
||||||
break;
|
case 'audits':
|
||||||
case 'overdue':
|
|
||||||
$assets->overdueForAudit($settings);
|
switch ($upcoming_status) {
|
||||||
break;
|
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
|
// This is used by the sidenav, mostly
|
||||||
|
|
|
@ -854,11 +854,11 @@ class AssetsController extends Controller
|
||||||
return view('hardware/audit-due');
|
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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ use App\Models\Setting;
|
||||||
use App\Models\Supplier;
|
use App\Models\Supplier;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\View\Label as LabelView;
|
use App\View\Label as LabelView;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
class LabelsController extends Controller
|
class LabelsController extends Controller
|
||||||
|
@ -21,9 +22,9 @@ class LabelsController extends Controller
|
||||||
/**
|
/**
|
||||||
* Returns the Label view with test data
|
* Returns the Label view with test data
|
||||||
*
|
*
|
||||||
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
|
* @param string $labelName
|
||||||
* @param string $labelName
|
|
||||||
* @return \Illuminate\Contracts\View\View
|
* @return \Illuminate\Contracts\View\View
|
||||||
|
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
|
||||||
*/
|
*/
|
||||||
public function show(string $labelName)
|
public function show(string $labelName)
|
||||||
{
|
{
|
||||||
|
@ -66,7 +67,7 @@ class LabelsController extends Controller
|
||||||
$exampleAsset->model->category->id = 999999;
|
$exampleAsset->model->category->id = 999999;
|
||||||
$exampleAsset->model->category->name = trans('admin/labels/table.example_category');
|
$exampleAsset->model->category->name = trans('admin/labels/table.example_category');
|
||||||
|
|
||||||
$customFieldColumns = CustomField::all()->pluck('db_column');
|
$customFieldColumns = CustomField::where('field_encrypted', '=', 0)->pluck('db_column');
|
||||||
|
|
||||||
collect(explode(';', Setting::getSettings()->label2_fields))
|
collect(explode(';', Setting::getSettings()->label2_fields))
|
||||||
->filter()
|
->filter()
|
||||||
|
|
|
@ -11,6 +11,7 @@ use App\Models\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller handles all actions related to Licenses for
|
* This controller handles all actions related to Licenses for
|
||||||
|
@ -289,4 +290,106 @@ class LicensesController extends Controller
|
||||||
->with('item', $license)
|
->with('item', $license)
|
||||||
->with('maintained_list', $maintained_list);
|
->with('maintained_list', $maintained_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exports Licenses to CSV
|
||||||
|
*
|
||||||
|
* @author [G. Martinez]
|
||||||
|
* @since [v6.3]
|
||||||
|
* @return StreamedResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function getExportLicensesCsv()
|
||||||
|
{
|
||||||
|
$this->authorize('view', License::class);
|
||||||
|
\Debugbar::disable();
|
||||||
|
|
||||||
|
$response = new StreamedResponse(function () {
|
||||||
|
// Open output stream
|
||||||
|
$handle = fopen('php://output', 'w');
|
||||||
|
$licenses= License::with('company',
|
||||||
|
'manufacturer',
|
||||||
|
'category',
|
||||||
|
'supplier',
|
||||||
|
'adminuser',
|
||||||
|
'assignedusers')
|
||||||
|
->orderBy('created_at', 'DESC');
|
||||||
|
Company::scopeCompanyables($licenses)
|
||||||
|
->chunk(500, function ($licenses) use ($handle) {
|
||||||
|
$headers = [
|
||||||
|
// strtolower to prevent Excel from trying to open it as a SYLK file
|
||||||
|
strtolower(trans('general.id')),
|
||||||
|
trans('general.company'),
|
||||||
|
trans('general.name'),
|
||||||
|
trans('general.serial_number'),
|
||||||
|
trans('general.purchase_date'),
|
||||||
|
trans('general.purchase_cost'),
|
||||||
|
trans('general.order_number'),
|
||||||
|
trans('general.licenses_available'),
|
||||||
|
trans('admin/licenses/table.seats'),
|
||||||
|
trans('general.created_by'),
|
||||||
|
trans('general.depreciation'),
|
||||||
|
trans('general.updated_at'),
|
||||||
|
trans('admin/licenses/table.deleted_at'),
|
||||||
|
trans('general.email'),
|
||||||
|
trans('admin/hardware/form.fully_depreciated'),
|
||||||
|
trans('general.supplier'),
|
||||||
|
trans('admin/licenses/form.expiration'),
|
||||||
|
trans('admin/licenses/form.purchase_order'),
|
||||||
|
trans('admin/licenses/form.termination_date'),
|
||||||
|
trans('admin/licenses/form.maintained'),
|
||||||
|
trans('general.manufacturer'),
|
||||||
|
trans('general.category'),
|
||||||
|
trans('general.min_amt'),
|
||||||
|
trans('admin/licenses/form.reassignable'),
|
||||||
|
trans('general.notes'),
|
||||||
|
trans('general.created_at'),
|
||||||
|
];
|
||||||
|
|
||||||
|
fputcsv($handle, $headers);
|
||||||
|
|
||||||
|
foreach ($licenses as $license) {
|
||||||
|
// Add a new row with data
|
||||||
|
$values = [
|
||||||
|
$license->id,
|
||||||
|
$license->company ? $license->company->name: '',
|
||||||
|
$license->name,
|
||||||
|
$license->serial,
|
||||||
|
$license->purchase_date,
|
||||||
|
$license->purchase_cost,
|
||||||
|
$license->order_number,
|
||||||
|
$license->free_seat_count,
|
||||||
|
$license->seats,
|
||||||
|
$license->adminuser->present()->fullName(),
|
||||||
|
$license->depreciation ? $license->depreciation->name: '',
|
||||||
|
$license->updated_at,
|
||||||
|
$license->deleted_at,
|
||||||
|
$license->email,
|
||||||
|
( $license->depreciate == '1') ? trans('general.yes') : trans('general.no'),
|
||||||
|
($license->supplier) ? $license->supplier->name: '',
|
||||||
|
$license->expiration_date,
|
||||||
|
$license->purchase_order,
|
||||||
|
$license->termination_date,
|
||||||
|
( $license->maintained == '1') ? trans('general.yes') : trans('general.no'),
|
||||||
|
$license->manufacturer ? $license->manufacturer->name: '',
|
||||||
|
$license->category ? $license->category->name: '',
|
||||||
|
$license->min_amt,
|
||||||
|
( $license->reassignable == '1') ? trans('general.yes') : trans('general.no'),
|
||||||
|
$license->notes,
|
||||||
|
$license->created_at,
|
||||||
|
];
|
||||||
|
|
||||||
|
fputcsv($handle, $values);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close the output stream
|
||||||
|
fclose($handle);
|
||||||
|
}, 200, [
|
||||||
|
'Content-Type' => 'text/csv; charset=UTF-8',
|
||||||
|
'Content-Disposition' => 'attachment; filename="licenses-'.date('Y-m-d-his').'.csv"',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -804,10 +804,9 @@ class SettingsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function getLabels()
|
public function getLabels()
|
||||||
{
|
{
|
||||||
return view('settings.labels', [
|
return view('settings.labels')
|
||||||
'setting' => Setting::getSettings(),
|
->with('setting', Setting::getSettings())
|
||||||
'customFields' => CustomField::all(),
|
->with('customFields', CustomField::where('field_encrypted', '=', 0)->get());
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace App\Http\Middleware;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use Auth;
|
use Auth;
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use App\Models\Setting;
|
||||||
|
|
||||||
class AssetCountForSidebar
|
class AssetCountForSidebar
|
||||||
{
|
{
|
||||||
|
@ -24,6 +25,13 @@ class AssetCountForSidebar
|
||||||
\Log::debug($e);
|
\Log::debug($e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$total_assets = Asset::RTD()->count();
|
||||||
|
view()->share('total_assets', $total_assets);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
\Log::debug($e);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$total_deployed_sidebar = Asset::Deployed()->count();
|
$total_deployed_sidebar = Asset::Deployed()->count();
|
||||||
view()->share('total_deployed_sidebar', $total_deployed_sidebar);
|
view()->share('total_deployed_sidebar', $total_deployed_sidebar);
|
||||||
|
@ -59,6 +67,44 @@ class AssetCountForSidebar
|
||||||
\Log::debug($e);
|
\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);
|
return $next($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Http\Requests;
|
||||||
|
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
|
use App\Models\Setting;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Carbon\Exceptions\InvalidFormatException;
|
use Carbon\Exceptions\InvalidFormatException;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
@ -45,12 +46,21 @@ class StoreAssetRequest extends ImageUploadRequest
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$rules = array_merge(
|
$modelRules = (new Asset)->getRules();
|
||||||
(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(),
|
parent::rules(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $rules;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function parseLastAuditDate(): void
|
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',
|
'eol_explicit' => 'boolean',
|
||||||
'last_checkout' => 'datetime',
|
'last_checkout' => 'datetime',
|
||||||
'last_checkin' => 'datetime',
|
'last_checkin' => 'datetime',
|
||||||
'expected_checkin' => 'date',
|
'expected_checkin' => 'datetime:m-d-Y',
|
||||||
'last_audit_date' => 'datetime',
|
'last_audit_date' => 'datetime',
|
||||||
'next_audit_date' => 'date',
|
'next_audit_date' => 'datetime:m-d-Y',
|
||||||
'model_id' => 'integer',
|
'model_id' => 'integer',
|
||||||
'status_id' => 'integer',
|
'status_id' => 'integer',
|
||||||
'company_id' => 'integer',
|
'company_id' => 'integer',
|
||||||
|
@ -1163,10 +1163,11 @@ class Asset extends Depreciable
|
||||||
public function scopeDueForAudit($query, $settings)
|
public function scopeDueForAudit($query, $settings)
|
||||||
{
|
{
|
||||||
$interval = $settings->audit_warning_days ?? 0;
|
$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')
|
return $query->whereNotNull('assets.next_audit_date')
|
||||||
->where('assets.next_audit_date', '>=', Carbon::now())
|
->whereBetween('assets.next_audit_date', [$today->format('Y-m-d'), $interval_date])
|
||||||
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'")
|
|
||||||
->where('assets.archived', '=', 0)
|
->where('assets.archived', '=', 0)
|
||||||
->NotArchived();
|
->NotArchived();
|
||||||
}
|
}
|
||||||
|
@ -1188,7 +1189,7 @@ class Asset extends Depreciable
|
||||||
public function scopeOverdueForAudit($query)
|
public function scopeOverdueForAudit($query)
|
||||||
{
|
{
|
||||||
return $query->whereNotNull('assets.next_audit_date')
|
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)
|
->where('assets.archived', '=', 0)
|
||||||
->NotArchived();
|
->NotArchived();
|
||||||
}
|
}
|
||||||
|
@ -1209,14 +1210,69 @@ class Asset extends Depreciable
|
||||||
|
|
||||||
public function scopeDueOrOverdueForAudit($query, $settings)
|
public function scopeDueOrOverdueForAudit($query, $settings)
|
||||||
{
|
{
|
||||||
$interval = $settings->audit_warning_days ?? 0;
|
|
||||||
|
|
||||||
return $query->whereNotNull('assets.next_audit_date')
|
return $query->where(function ($query) {
|
||||||
->whereRaw('DATE_SUB('.DB::getTablePrefix()."assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'")
|
$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)
|
->where('assets.archived', '=', 0)
|
||||||
|
->whereNotNull('assets.assigned_to')
|
||||||
->NotArchived();
|
->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
|
* 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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -81,6 +81,7 @@ class License extends Depreciable
|
||||||
'serial',
|
'serial',
|
||||||
'supplier_id',
|
'supplier_id',
|
||||||
'termination_date',
|
'termination_date',
|
||||||
|
'free_seat_count',
|
||||||
'user_id',
|
'user_id',
|
||||||
'min_amt',
|
'min_amt',
|
||||||
];
|
];
|
||||||
|
@ -114,6 +115,7 @@ class License extends Depreciable
|
||||||
'category' => ['name'],
|
'category' => ['name'],
|
||||||
'depreciation' => ['name'],
|
'depreciation' => ['name'],
|
||||||
];
|
];
|
||||||
|
protected $appends = ['free_seat_count'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update seat counts when the license is updated
|
* Update seat counts when the license is updated
|
||||||
|
@ -280,6 +282,16 @@ class License extends Depreciable
|
||||||
}
|
}
|
||||||
$this->attributes['termination_date'] = $value;
|
$this->attributes['termination_date'] = $value;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Sets free_seat_count attribute
|
||||||
|
*
|
||||||
|
* @author G. Martinez
|
||||||
|
* @since [v6.3]
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getFreeSeatCountAttribute(){
|
||||||
|
return $this->attributes['free_seat_count'] = $this->remaincount();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Establishes the license -> company relationship
|
* Establishes the license -> company relationship
|
||||||
|
@ -502,7 +514,13 @@ class License extends Depreciable
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->count();
|
->count();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Returns the available seats remaining
|
||||||
|
*
|
||||||
|
* @author A. Gianotto <snipe@snipe.net>
|
||||||
|
* @since [v2.0]
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of total available seats for this license
|
* Returns the number of total available seats for this license
|
||||||
|
@ -579,7 +597,7 @@ class License extends Depreciable
|
||||||
$taken = $this->assigned_seats_count;
|
$taken = $this->assigned_seats_count;
|
||||||
$diff = ($total - $taken);
|
$diff = ($total - $taken);
|
||||||
|
|
||||||
return $diff;
|
return (int) $diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -900,4 +900,10 @@ input[type="radio"]:checked::before {
|
||||||
}
|
}
|
||||||
.datepicker.dropdown-menu {
|
.datepicker.dropdown-menu {
|
||||||
z-index: 1030 !important;
|
z-index: 1030 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-menu > li .badge {
|
||||||
|
margin-top: 0px;
|
||||||
|
filter: brightness(70%);
|
||||||
|
font-size: 70%;
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ return array(
|
||||||
|
|
||||||
'assigned_to' => 'Assigned To',
|
'assigned_to' => 'Assigned To',
|
||||||
'checkout' => 'In/Out',
|
'checkout' => 'In/Out',
|
||||||
|
'deleted_at' => 'Deleted at',
|
||||||
'id' => 'ID',
|
'id' => 'ID',
|
||||||
'license_email' => 'License Email',
|
'license_email' => 'License Email',
|
||||||
'license_name' => 'Licensed To',
|
'license_name' => 'Licensed To',
|
||||||
|
|
|
@ -176,7 +176,7 @@ return [
|
||||||
'last_name' => 'Last Name',
|
'last_name' => 'Last Name',
|
||||||
'license' => 'License',
|
'license' => 'License',
|
||||||
'license_report' => 'License Report',
|
'license_report' => 'License Report',
|
||||||
'licenses_available' => 'licenses available',
|
'licenses_available' => 'Licenses available',
|
||||||
'licenses' => 'Licenses',
|
'licenses' => 'Licenses',
|
||||||
'list_all' => 'List All',
|
'list_all' => 'List All',
|
||||||
'loading' => 'Loading... please wait....',
|
'loading' => 'Loading... please wait....',
|
||||||
|
@ -313,6 +313,10 @@ return [
|
||||||
'token_expired' => 'Your form session has expired. Please try again.',
|
'token_expired' => 'Your form session has expired. Please try again.',
|
||||||
'login_enabled' => 'Login Enabled',
|
'login_enabled' => 'Login Enabled',
|
||||||
'audit_due' => 'Due for Audit',
|
'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',
|
'audit_overdue' => 'Overdue for Audit',
|
||||||
'accept' => 'Accept :asset',
|
'accept' => 'Accept :asset',
|
||||||
'i_accept' => 'I accept',
|
'i_accept' => 'I accept',
|
||||||
|
|
|
@ -1,40 +1,59 @@
|
||||||
@extends('layouts/default')
|
@extends('layouts/default')
|
||||||
|
|
||||||
@section('title0')
|
|
||||||
|
|
||||||
@if ((Request::get('company_id')) && ($company))
|
|
||||||
{{ $company->name }}
|
|
||||||
@endif
|
|
||||||
|
|
||||||
{{ trans('general.audit_due') }}
|
|
||||||
|
|
||||||
@stop
|
|
||||||
|
|
||||||
{{-- Page title --}}
|
{{-- Page title --}}
|
||||||
@section('title')
|
@section('title')
|
||||||
@yield('title0') @parent
|
{{ trans_choice('general.audit_due_days', $settings->audit_warning_days, ['days' => $settings->audit_warning_days]) }}
|
||||||
@stop
|
@stop
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{{-- Page content --}}
|
{{-- Page content --}}
|
||||||
@section('content')
|
@section('content')
|
||||||
|
{{-- Page content --}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<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="row">
|
||||||
|
<div class="table table-responsive">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
|
||||||
<table
|
<table
|
||||||
data-click-to-select="true"
|
data-click-to-select="true"
|
||||||
data-columns="{{ \App\Presenters\AssetAuditPresenter::dataTableLayout() }}"
|
data-columns="{{ \App\Presenters\AssetAuditPresenter::dataTableLayout() }}"
|
||||||
data-cookie-id-table="assetsAuditListingTable"
|
data-cookie-id-table="dueAssetAuditListing"
|
||||||
data-pagination="true"
|
data-pagination="true"
|
||||||
data-id-table="assetsAuditListingTable"
|
data-id-table="dueAssetAuditListing"
|
||||||
data-search="true"
|
data-search="true"
|
||||||
data-side-pagination="server"
|
data-side-pagination="server"
|
||||||
data-show-columns="true"
|
data-show-columns="true"
|
||||||
|
@ -44,28 +63,71 @@
|
||||||
data-show-refresh="true"
|
data-show-refresh="true"
|
||||||
data-sort-order="asc"
|
data-sort-order="asc"
|
||||||
data-sort-name="name"
|
data-sort-name="name"
|
||||||
data-toolbar="#assetsBulkEditToolbar"
|
data-toolbar="#dueAssetEditToolbar"
|
||||||
data-bulk-button-id="#bulkAssetEditButton"
|
data-bulk-button-id="#dueAssetEditButton"
|
||||||
data-bulk-form-id="#assetsBulkForm"
|
data-bulk-form-id="#dueAssetEditForm"
|
||||||
id="assetsAuditListingTable"
|
id="#dueAssetAuditListing"
|
||||||
class="table table-striped snipe-table"
|
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='{
|
data-export-options='{
|
||||||
"fileName": "export-assets-due-audit-{{ date('Y-m-d') }}",
|
"fileName": "export-assets-due-audit-{{ date('Y-m-d') }}",
|
||||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||||
}'>
|
}'>
|
||||||
</table>
|
</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><!-- /.col -->
|
||||||
</div><!-- /.row -->
|
</div><!-- /.row -->
|
||||||
{{ Form::close() }}
|
|
||||||
</div><!-- ./box-body -->
|
|
||||||
</div><!-- /.box -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@stop
|
@stop
|
||||||
|
|
||||||
@section('moar_scripts')
|
@section('moar_scripts')
|
||||||
@include('partials.bootstrap-table')
|
@include('partials.bootstrap-table')
|
||||||
|
|
||||||
@stop
|
@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>
|
<i class="far fa-save fa-2x" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="hidden-xs hidden-sm">{{ trans('general.licenses') }}
|
<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>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
<i class="far fa-hdd fa-2x" aria-hidden="true"></i>
|
<i class="far fa-hdd fa-2x" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="hidden-xs hidden-sm">{{ trans('general.components') }}
|
<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>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
<i class="fas fa-barcode fa-2x" aria-hidden="true"></i>
|
<i class="fas fa-barcode fa-2x" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="hidden-xs hidden-sm">{{ trans('general.assets') }}
|
<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>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
<i class="fas fa-wrench fa-2x" aria-hidden="true"></i>
|
<i class="fas fa-wrench fa-2x" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="hidden-xs hidden-sm">{{ trans('general.maintenances') }}
|
<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>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -107,7 +107,7 @@
|
||||||
<i class="far fa-file fa-2x" aria-hidden="true"></i>
|
<i class="far fa-file fa-2x" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="hidden-xs hidden-sm">{{ trans('general.files') }}
|
<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>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -119,7 +119,7 @@
|
||||||
</span>
|
</span>
|
||||||
<span class="hidden-xs hidden-sm">
|
<span class="hidden-xs hidden-sm">
|
||||||
{{ trans('general.additional_files') }}
|
{{ 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>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -437,6 +437,9 @@
|
||||||
<a href="{{ url('hardware') }}">
|
<a href="{{ url('hardware') }}">
|
||||||
<i class="far fa-circle text-grey fa-fw" aria-hidden="true"></i>
|
<i class="far fa-circle text-grey fa-fw" aria-hidden="true"></i>
|
||||||
{{ trans('general.list_all') }}
|
{{ trans('general.list_all') }}
|
||||||
|
<span class="badge">
|
||||||
|
{{ (isset($total_assets)) ? $total_assets : '' }}
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
@ -447,7 +450,8 @@
|
||||||
<a href="{{ route('statuslabels.show', ['statuslabel' => $status_nav->id]) }}">
|
<a href="{{ route('statuslabels.show', ['statuslabel' => $status_nav->id]) }}">
|
||||||
<i class="fas fa-circle text-grey fa-fw"
|
<i class="fas fa-circle text-grey fa-fw"
|
||||||
aria-hidden="true"{!! ($status_nav->color!='' ? ' style="color: '.e($status_nav->color).'"' : '') !!}></i>
|
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
|
@endforeach
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@ -455,49 +459,43 @@
|
||||||
<li{!! (Request::query('status') == 'Deployed' ? ' class="active"' : '') !!}>
|
<li{!! (Request::query('status') == 'Deployed' ? ' class="active"' : '') !!}>
|
||||||
<a href="{{ url('hardware?status=Deployed') }}">
|
<a href="{{ url('hardware?status=Deployed') }}">
|
||||||
<i class="far fa-circle text-blue fa-fw"></i>
|
<i class="far fa-circle text-blue fa-fw"></i>
|
||||||
{{ trans('general.all') }}
|
|
||||||
{{ trans('general.deployed') }}
|
{{ trans('general.deployed') }}
|
||||||
({{ (isset($total_deployed_sidebar)) ? $total_deployed_sidebar : '' }})
|
<span class="badge">{{ (isset($total_deployed_sidebar)) ? $total_deployed_sidebar : '' }}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li{!! (Request::query('status') == 'RTD' ? ' class="active"' : '') !!}>
|
<li{!! (Request::query('status') == 'RTD' ? ' class="active"' : '') !!}>
|
||||||
<a href="{{ url('hardware?status=RTD') }}">
|
<a href="{{ url('hardware?status=RTD') }}">
|
||||||
<i class="far fa-circle text-green fa-fw"></i>
|
<i class="far fa-circle text-green fa-fw"></i>
|
||||||
{{ trans('general.all') }}
|
|
||||||
{{ trans('general.ready_to_deploy') }}
|
{{ trans('general.ready_to_deploy') }}
|
||||||
({{ (isset($total_rtd_sidebar)) ? $total_rtd_sidebar : '' }})
|
<span class="badge">{{ (isset($total_rtd_sidebar)) ? $total_rtd_sidebar : '' }}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li{!! (Request::query('status') == 'Pending' ? ' class="active"' : '') !!}><a
|
<li{!! (Request::query('status') == 'Pending' ? ' class="active"' : '') !!}><a
|
||||||
href="{{ url('hardware?status=Pending') }}"><i
|
href="{{ url('hardware?status=Pending') }}"><i
|
||||||
class="far fa-circle text-orange fa-fw"></i>
|
class="far fa-circle text-orange fa-fw"></i>
|
||||||
{{ trans('general.all') }}
|
|
||||||
{{ trans('general.pending') }}
|
{{ trans('general.pending') }}
|
||||||
({{ (isset($total_pending_sidebar)) ? $total_pending_sidebar : '' }})
|
<span class="badge">{{ (isset($total_pending_sidebar)) ? $total_pending_sidebar : '' }}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li{!! (Request::query('status') == 'Undeployable' ? ' class="active"' : '') !!} ><a
|
<li{!! (Request::query('status') == 'Undeployable' ? ' class="active"' : '') !!} ><a
|
||||||
href="{{ url('hardware?status=Undeployable') }}"><i
|
href="{{ url('hardware?status=Undeployable') }}"><i
|
||||||
class="fas fa-times text-red fa-fw"></i>
|
class="fas fa-times text-red fa-fw"></i>
|
||||||
{{ trans('general.all') }}
|
|
||||||
{{ trans('general.undeployable') }}
|
{{ trans('general.undeployable') }}
|
||||||
({{ (isset($total_undeployable_sidebar)) ? $total_undeployable_sidebar : '' }})
|
<span class="badge">{{ (isset($total_undeployable_sidebar)) ? $total_undeployable_sidebar : '' }}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li{!! (Request::query('status') == 'byod' ? ' class="active"' : '') !!}><a
|
<li{!! (Request::query('status') == 'byod' ? ' class="active"' : '') !!}><a
|
||||||
href="{{ url('hardware?status=byod') }}"><i
|
href="{{ url('hardware?status=byod') }}"><i
|
||||||
class="fas fa-times text-red fa-fw"></i>
|
class="fas fa-times text-red fa-fw"></i>
|
||||||
{{ trans('general.all') }}
|
|
||||||
{{ trans('general.byod') }}
|
{{ trans('general.byod') }}
|
||||||
({{ (isset($total_byod_sidebar)) ? $total_byod_sidebar : '' }})
|
<span class="badge">{{ (isset($total_byod_sidebar)) ? $total_byod_sidebar : '' }}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li{!! (Request::query('status') == 'Archived' ? ' class="active"' : '') !!}><a
|
<li{!! (Request::query('status') == 'Archived' ? ' class="active"' : '') !!}><a
|
||||||
href="{{ url('hardware?status=Archived') }}"><i
|
href="{{ url('hardware?status=Archived') }}"><i
|
||||||
class="fas fa-times text-red fa-fw"></i>
|
class="fas fa-times text-red fa-fw"></i>
|
||||||
{{ trans('general.all') }}
|
|
||||||
{{ trans('admin/hardware/general.archived') }}
|
{{ trans('admin/hardware/general.archived') }}
|
||||||
({{ (isset($total_archived_sidebar)) ? $total_archived_sidebar : '' }})
|
<span class="badge">{{ (isset($total_archived_sidebar)) ? $total_archived_sidebar : '' }}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li{!! (Request::query('status') == 'Requestable' ? ' class="active"' : '') !!}><a
|
<li{!! (Request::query('status') == 'Requestable' ? ' class="active"' : '') !!}><a
|
||||||
|
@ -511,13 +509,18 @@
|
||||||
<li{!! (Request::is('hardware/audit/due') ? ' class="active"' : '') !!}>
|
<li{!! (Request::is('hardware/audit/due') ? ' class="active"' : '') !!}>
|
||||||
<a href="{{ route('assets.audit.due') }}">
|
<a href="{{ route('assets.audit.due') }}">
|
||||||
<i class="fas fa-history text-yellow fa-fw"></i> {{ trans('general.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>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li{!! (Request::is('hardware/audit/overdue') ? ' class="active"' : '') !!}>
|
@endcan
|
||||||
<a href="{{ route('assets.audit.overdue') }}">
|
|
||||||
<i class="fas fa-exclamation-triangle text-red fa-fw"></i> {{ trans('general.audit_overdue') }}
|
@can('checkin', \App\Models\Asset::class)
|
||||||
</a>
|
<li{!! (Request::is('hardware/checkins/due') ? ' class="active"' : '') !!}>
|
||||||
</li>
|
<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
|
@endcan
|
||||||
|
|
||||||
<li class="divider"> </li>
|
<li class="divider"> </li>
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
{{ trans('general.create') }}
|
{{ trans('general.create') }}
|
||||||
</a>
|
</a>
|
||||||
@endcan
|
@endcan
|
||||||
|
@can('view', \App\Models\License::class)
|
||||||
|
<a class="btn btn-default pull-right" href="{{ route('licenses.export') }}" style="margin-right: 5px;">{{ trans('general.export') }}</a>
|
||||||
|
@endcan
|
||||||
@stop
|
@stop
|
||||||
|
|
||||||
{{-- Page content --}}
|
{{-- Page content --}}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
@php
|
@php
|
||||||
$checkin = Helper::getFormattedDateObject($asset->expected_checkin, 'date');
|
$checkin = Helper::getFormattedDateObject($asset->expected_checkin, 'date');
|
||||||
@endphp
|
@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
|
@endforeach
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|
||||||
|
|
|
@ -351,6 +351,7 @@
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="Custom Fields">
|
<optgroup label="Custom Fields">
|
||||||
@foreach($customFields as $customField)
|
@foreach($customFields as $customField)
|
||||||
|
|
||||||
<option value="{{ $customField->db_column }}">{{ $customField->name }}</option>
|
<option value="{{ $customField->db_column }}">{{ $customField->name }}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</optgroup>
|
</optgroup>
|
||||||
|
|
|
@ -496,13 +496,27 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:api']], functi
|
||||||
)->name('api.assets.show.byserial')
|
)->name('api.assets.show.byserial')
|
||||||
->where('any', '.*');
|
->where('any', '.*');
|
||||||
|
|
||||||
Route::get('audit/{audit}',
|
// LEGACY URL - Get assets that are due or overdue for audit
|
||||||
|
Route::get('audit/{status}',
|
||||||
[
|
[
|
||||||
Api\AssetsController::class,
|
Api\AssetsController::class,
|
||||||
'index'
|
'index'
|
||||||
]
|
]
|
||||||
)->name('api.asset.to-audit');
|
)->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',
|
Route::post('audit',
|
||||||
[
|
[
|
||||||
Api\AssetsController::class,
|
Api\AssetsController::class,
|
||||||
|
|
|
@ -50,26 +50,10 @@ Route::group(
|
||||||
[AssetsController::class, 'dueForAudit']
|
[AssetsController::class, 'dueForAudit']
|
||||||
)->name('assets.audit.due');
|
)->name('assets.audit.due');
|
||||||
|
|
||||||
Route::get('audit/overdue',
|
Route::get('checkins/due',
|
||||||
[AssetsController::class, 'overdueForAudit']
|
[AssetsController::class, 'dueForCheckin']
|
||||||
)->name('assets.audit.overdue');
|
)->name('assets.checkins.due');
|
||||||
|
|
||||||
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('audit/{id}',
|
Route::get('audit/{id}',
|
||||||
[AssetsController::class, 'audit']
|
[AssetsController::class, 'audit']
|
||||||
)->name('asset.audit.create');
|
)->name('asset.audit.create');
|
||||||
|
|
|
@ -48,6 +48,13 @@ Route::group(['prefix' => 'licenses', 'middleware' => ['auth']], function () {
|
||||||
'{licenseId}/showfile/{fileId}/{download?}',
|
'{licenseId}/showfile/{fileId}/{download?}',
|
||||||
[Licenses\LicenseFilesController::class, 'show']
|
[Licenses\LicenseFilesController::class, 'show']
|
||||||
)->name('show.licensefile');
|
)->name('show.licensefile');
|
||||||
|
Route::get(
|
||||||
|
'export',
|
||||||
|
[
|
||||||
|
Licenses\LicensesController::class,
|
||||||
|
'getExportLicensesCsv'
|
||||||
|
]
|
||||||
|
)->name('licenses.export');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::resource('licenses', Licenses\LicensesController::class, [
|
Route::resource('licenses', Licenses\LicensesController::class, [
|
||||||
|
|
|
@ -7,10 +7,10 @@ use App\Models\Company;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Testing\Fluent\AssertableJson;
|
use Illuminate\Testing\Fluent\AssertableJson;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
use Carbon\Carbon;
|
||||||
class AssetIndexTest extends TestCase
|
class AssetIndexTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testAssetIndexReturnsExpectedAssets()
|
public function testAssetApiIndexReturnsExpectedAssets()
|
||||||
{
|
{
|
||||||
Asset::factory()->count(3)->create();
|
Asset::factory()->count(3)->create();
|
||||||
|
|
||||||
|
@ -30,7 +30,102 @@ class AssetIndexTest extends TestCase
|
||||||
->assertJson(fn(AssertableJson $json) => $json->has('rows', 3)->etc());
|
->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();
|
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Tests\Feature\Api\Assets;
|
namespace Tests\Feature\Api\Assets;
|
||||||
|
|
||||||
|
use App\Helpers\Helper;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\AssetModel;
|
use App\Models\AssetModel;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
|
@ -12,6 +13,7 @@ use App\Models\Supplier;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\Crypt;
|
use Illuminate\Support\Facades\Crypt;
|
||||||
use Illuminate\Testing\Fluent\AssertableJson;
|
use Illuminate\Testing\Fluent\AssertableJson;
|
||||||
|
use Illuminate\Testing\TestResponse;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class AssetStoreTest extends TestCase
|
class AssetStoreTest extends TestCase
|
||||||
|
@ -278,6 +280,50 @@ class AssetStoreTest extends TestCase
|
||||||
->assertStatusMessageIs('error');
|
->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()
|
public function testUniqueSerialNumbersIsEnforcedWhenEnabled()
|
||||||
{
|
{
|
||||||
$model = AssetModel::factory()->create();
|
$model = AssetModel::factory()->create();
|
||||||
|
|
|
@ -16,4 +16,13 @@ class HelperTest extends TestCase
|
||||||
{
|
{
|
||||||
$this->assertIsString(Helper::defaultChartColors(-1));
|
$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'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue