Auduting improvements

This commit is contained in:
snipe 2017-08-25 18:40:20 -07:00
parent af835d6efc
commit 51d74ac06d
15 changed files with 189 additions and 23 deletions

View file

@ -512,18 +512,25 @@ class AssetsController extends Controller
$this->authorize('audit', Asset::class);
$rules = array(
'id' => 'required'
'location_id' => 'exists:locations,id|nullable|numeric',
'next_audit_date' => 'date|nullable'
);
$validator = \Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
}
$asset = Asset::findOrFail($id);
$asset->next_audit_date = $request->input('next_audit_date');
if ($asset->save()) {
$asset->logAudit(request('note'));
$asset->logAudit(request('note'),request('location_id'));
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.audit.success')));
}
}
}

View file

@ -19,7 +19,7 @@ class ReportsController extends Controller
public function index(Request $request)
{
$actionlogs = Actionlog::with('item', 'user', 'target');
$actionlogs = Actionlog::with('item', 'user', 'target','location');
if ($request->has('search')) {
$actionlogs = $actionlogs->TextSearch(e($request->input('search')));

View file

@ -1241,22 +1241,30 @@ class AssetsController extends Controller
public function audit(Request $request, $id)
{
$this->authorize('audit', Asset::class);
$dt = Carbon::now()->addMonths(12)->toDateString();
$asset = Asset::findOrFail($id);
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt);
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt)->with('locations_list', Helper::locationsList());
}
public function auditStore(Request $request, $id)
{
$this->authorize('audit', Asset::class);
$rules = array(
'location_id' => 'exists:locations,id|nullable|numeric',
'next_audit_date' => 'date|nullable'
);
$validator = \Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
}
$asset = Asset::findOrFail($id);
$asset->next_audit_date = $request->input('next_audit_date');
if ($asset->save()) {
$asset->logAudit(request('note'));
$asset->logAudit(request('note'),request('location_id'));
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.audit.success'));
}
}

View file

@ -562,10 +562,12 @@ class SettingsController extends Controller
$alert_email = rtrim($request->input('alert_email'), ',');
$alert_email = trim($alert_email);
$setting->alert_email = e($alert_email);
$setting->alert_email = $alert_email;
$setting->alerts_enabled = $request->input('alerts_enabled', '0');
$setting->alert_interval = $request->input('alert_interval');
$setting->alert_threshold = $request->input('alert_threshold');
$setting->audit_interval = $request->input('audit_interval');
$setting->audit_warning_days = $request->input('audit_warning_days');
if ($setting->save()) {
return redirect()->route('settings.index')

View file

@ -2,6 +2,7 @@
namespace App\Http\Transformers;
use App\Models\Actionlog;
use App\Models\Setting;
use Gate;
use Illuminate\Database\Eloquent\Collection;
use App\Helpers\Helper;
@ -12,24 +13,32 @@ class ActionlogsTransformer
public function transformActionlogs (Collection $actionlogs, $total)
{
$array = array();
$settings = Setting::getSettings();
foreach ($actionlogs as $actionlog) {
$array[] = self::transformActionlog($actionlog);
$array[] = self::transformActionlog($actionlog, $settings);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformActionlog (Actionlog $actionlog)
public function transformActionlog (Actionlog $actionlog, $settings = null)
{
$array = [
'id' => (int) $actionlog->id,
'icon' => $actionlog->present()->icon(),
'image' => ($actionlog->item->getImageUrl()) ? $actionlog->item->getImageUrl() : null,
'item' => ($actionlog->item) ? [
'id' => (int) $actionlog->item->id,
'name' => e($actionlog->item->getDisplayNameAttribute()),
'type' => e($actionlog->itemType()),
] : null,
'location' => ($actionlog->location) ? [
'id' => (int) $actionlog->location->id,
'name' => e($actionlog->location->name)
] : null,
'created_at' => Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($actionlog->updated_at, 'datetime'),
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->item->next_audit_date, 'datetime'): null,
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->item->next_audit_date, 'date'): null,
'days_to_next_audit' => $actionlog->daysUntilNextAudit($settings->audit_interval, $actionlog->item),
'action_type' => $actionlog->present()->actionType(),
'admin' => ($actionlog->user) ? [
'id' => (int) $actionlog->user->id,

View file

@ -123,6 +123,10 @@ class Actionlog extends SnipeModel
return $this->belongsTo('\App\Models\ActionLog', 'thread_id');
}
public function location() {
return $this->belongsTo('\App\Models\Location', 'location_id' )->withTrashed();
}
/**
* Check if the file exists, and if it does, force a download
**/
@ -149,6 +153,44 @@ class Actionlog extends SnipeModel
}
}
public function daysUntilNextAudit($monthInterval = null, $asset = null) {
// check for next_audit_date to override global
if (!$monthInterval) {
$monthInterval = 12;
}
$last_audit_date = $this->created_at;
$next_audit_days = $last_audit_date->diffInDays($last_audit_date->copy()->addMonth($monthInterval));
// Override the default setting for interval if the asset has its own next audit date
if (($asset) && ($asset->next_audit_date)) {
$override_default_next = \Carbon::parse($asset->next_audit_date);
$suborder['payment_date'] = $override_default_next->format('M d Y');
$next_audit_days = $last_audit_date->diffInDays($override_default_next);
}
return $next_audit_days;
}
public function calcNextAuditDate($monthInterval = null, $asset = null) {
if (!$monthInterval) {
$monthInterval = 12;
}
$dt = \Carbon::now()->addMonths(12)->toDateString();
$last_audit_date = Carbon::parse($this->created_at);
// If there is an asset-specific next date already given,
if (($asset) && ($asset->next_audit_date)) {
return \Carbon::parse($asset->next_audit_date);;
}
$next_audit_date = \Carbon::now()->addMonths($monthInterval)->toDateString();
$next_audit_date = $last_audit_date->diffInDays($last_audit_date->copy()->addMonth($monthInterval));
}
/**
* getListingOfActionLogsChronologicalOrder
*

View file

@ -66,6 +66,7 @@ class Asset extends Depreciable
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
'status' => 'integer',
'purchase_cost' => 'numeric|nullable',
'next_audit_date' => 'date|nullable',
];
/**

View file

@ -127,7 +127,7 @@ trait Loggable
* @since [v4.0]
* @return \App\Models\Actionlog
*/
public function logAudit($note)
public function logAudit($note, $location_id)
{
$log = new Actionlog;
if (static::class == LicenseSeat::class) {
@ -137,7 +137,7 @@ trait Loggable
$log->item_type = static::class;
$log->item_id = $this->id;
}
$log->location_id = null;
$log->location_id = ($location_id) ? $location_id : null;
$log->note = $note;
$log->user_id = Auth::user()->id;
$log->logaction('audit');
@ -153,6 +153,7 @@ trait Loggable
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.5]

View file

@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddAuditingToSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->integer('audit_interval')->nullable()->default(NULL);
$table->integer('audit_warning_days')->nullable()->default(NULL);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('audit_interval');
$table->dropColumn('audit_warning_days');
});
}
}

View file

@ -10,6 +10,10 @@ return array(
'alert_interval' => 'Expiring Alerts Threshold (in days)',
'alert_inv_threshold' => 'Inventory Alert Threshold',
'asset_ids' => 'Asset IDs',
'audit_interval' => 'Audit Interval',
'audit_interval_help' => 'If you are required to regularly physically audit your assets, enter the interval in months.',
'audit_warning_days' => 'Audit Warning Threshold',
'audit_warning_days_help' => 'How many days in advance should we warn you when assets are due for auditing?',
'auto_increment_assets' => 'Generate auto-incrementing asset IDs',
'auto_increment_prefix' => 'Prefix (optional)',
'auto_incrementing_help' => 'Enable auto-incrementing asset IDs first to set this',

View file

@ -54,6 +54,8 @@
'current' => 'Current',
'custom_report' => 'Custom Asset Report',
'dashboard' => 'Dashboard',
'days' => 'days',
'days_to_next_audit' => 'Days to Next Audit',
'date' => 'Date',
'debug_warning' => 'Warning!',
'debug_warning_text' => 'This application is running in production mode with debugging enabled. This can expose sensitive data if your application is accessible to the outside world. Disable debug mode by setting the <code>APP_DEBUG</code> value in your <code>.env</code> file to <code>false</code>.',

View file

@ -44,11 +44,20 @@
</div>
</div>
<!-- Locations -->
<div id="location_id" class="form-group{{ $errors->has('location_id') ? ' has-error' : '' }}">
{{ Form::label('location_id', trans('general.location'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-9">
{{ Form::select('location_id', $locations_list , Input::old('location_id'), array('class'=>'select2', 'id'=>'location_id', 'style'=>'width:100%')) }}
{!! $errors->first('location_id', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>
<!-- Next Audit -->
<div class="form-group {{ $errors->has('next_audit_date') ? 'error' : '' }}">
{{ Form::label('name', trans('admin/hardware/form.checkout_date'), array('class' => 'col-md-3 control-label')) }}
{{ Form::label('name', trans('general.next_audit_date'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-9">
<div class="input-group date col-md-5" data-provide="datepicker" data-date-format="yyyy-mm-dd">
<input type="text" class="form-control" placeholder="{{ trans('general.next_audit_date') }}" name="next_audit_date" id="next_audit_date" value="{{ Input::old('next_audit_date', $next_audit_date) }}">
@ -73,7 +82,7 @@
</div> <!--/.box-body-->
<div class="box-footer">
<a class="btn btn-link" href="{{ URL::previous() }}"> {{ trans('button.cancel') }}</a>
<button type="submit" class="btn btn-success pull-right"><i class="fa fa-check icon-white"></i> {{ trans('general.checkout') }}</button>
<button type="submit" class="btn btn-success pull-right"><i class="fa fa-check icon-white"></i> {{ trans('general.audit') }}</button>
</div>
</form>
</div>

View file

@ -98,6 +98,15 @@ $('.snipe-table').bootstrapTable({
});
function dateRowCheckStyle(value) {
if ((value.days_to_next_audit) && (value.days_to_next_audit < {{ $snipeSettings->audit_warning_days }})) {
return { classes : "danger" }
}
return {};
}
// Handle whether or not the edit button should be disabled
$('.snipe-table').on('check.bs.table', function () {
$('#bulkEdit').removeAttr('disabled');

View file

@ -15,22 +15,25 @@
<div class="box-body">
<table
name="activityReport"
name="auditReport"
data-toolbar="#toolbar"
class="table table-striped snipe-table"
id="table"
data-url="{{ route('api.activity.index', ['action_type' => 'audit']) }}"
data-cookie="true"
data-cookie-id-table="activityReportTable">
data-cookie-id-table="activityReportTable"
data-row-style="dateRowCheckStyle">
<thead>
<tr>
<th data-field="icon" style="width: 40px;" class="hidden-xs" data-formatter="iconFormatter"></th>
<th class="col-sm-3" data-field="created_at" data-formatter="dateDisplayFormatter">{{ trans('general.date') }}</th>
<th class="col-sm-1" data-field="image" data-visible="false" data-formatter="imageFormatter">{{ trans('admin/hardware/table.image') }}</th>
<th class="col-sm-2" data-field="created_at" data-formatter="dateDisplayFormatter">{{ trans('general.audit') }}</th>
<th class="col-sm-2" data-field="admin" data-formatter="usersLinkObjFormatter">{{ trans('general.admin') }}</th>
<th class="col-sm-2" data-field="action_type">{{ trans('general.action') }}</th>
<th class="col-sm-3" data-field="item" data-formatter="polymorphicItemFormatter">{{ trans('general.item') }}</th>
<th class="col-sm-2" data-field="item" data-formatter="polymorphicItemFormatter">{{ trans('general.item') }}</th>
<th class="col-sm-1" data-field="location" data-formatter="locationsLinkObjFormatter">{{ trans('general.location') }}</th>
<th class="col-sm-2" data-field="next_audit_date" data-formatter="dateDisplayFormatter">{{ trans('general.next_audit_date') }}</th>
<th class="col-sm-1" data-field="days_to_next_audit">{{ trans('general.days_to_next_audit') }}</th>
<th class="col-sm-1" data-field="note">{{ trans('general.notes') }}</th>
<th class="col-sm-2" data-field="note">{{ trans('general.notes') }}</th>
</tr>
</thead>
</table>
@ -42,5 +45,5 @@
@section('moar_scripts')
@include ('partials.bootstrap-table', ['exportFile' => 'activity-export', 'search' => true])
@include ('partials.bootstrap-table', ['exportFile' => 'audit-export', 'search' => false])
@stop

View file

@ -90,6 +90,41 @@
</div>
</div>
<!-- Alert interval -->
<div class="form-group {{ $errors->has('audit_interval') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('audit_interval', trans('admin/settings/general.audit_interval')) }}
</div>
<div class="input-group col-md-2">
{{ Form::text('audit_interval', Input::old('audit_interval', $setting->audit_interval), array('class' => 'form-control','placeholder' => '12', 'maxlength'=>'3', 'style'=>'width: 60px;')) }}
<span class="input-group-addon">{{ trans('general.months') }}</span>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('audit_interval', '<span class="alert-msg">:message</span>') !!}
<p class="help-block">{{ trans('admin/settings/general.audit_interval_help') }}</p>
</div>
</div>
<!-- Alert threshold -->
<div class="form-group {{ $errors->has('audit_warning_days') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('audit_warning_days', trans('admin/settings/general.audit_warning_days')) }}
</div>
<div class="input-group col-md-2">
{{ Form::text('audit_warning_days', Input::old('audit_warning_days', $setting->audit_warning_days), array('class' => 'form-control','placeholder' => '14', 'maxlength'=>'3', 'style'=>'width: 60px;')) }}
<span class="input-group-addon">{{ trans('general.days') }}</span>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('audit_warning_days', '<span class="alert-msg">:message</span>') !!}
<p class="help-block">{{ trans('admin/settings/general.audit_warning_days_help') }}</p>
</div>
</div>
</div>
</div> <!--/.box-body-->