Skip to content

Commit 16f57e1

Browse files
committed
Fixes #1190 - added basic audit workflow
1 parent af6f208 commit 16f57e1

File tree

18 files changed

+413
-5
lines changed

18 files changed

+413
-5
lines changed

app/Http/Controllers/Api/AssetsController.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use Validator;
3232
use View;
3333

34+
3435
/**
3536
* This class controls all actions related to assets for
3637
* the Snipe-IT Asset Management application.
@@ -496,4 +497,33 @@ public function checkin($asset_id)
496497

497498
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.error')));
498499
}
500+
501+
502+
/**
503+
* Mark an asset as audited
504+
*
505+
* @author [A. Gianotto] [<[email protected]>]
506+
* @param int $id
507+
* @since [v4.0]
508+
* @return JsonResponse
509+
*/
510+
public function audit(Request $request, $id) {
511+
512+
$this->authorize('audit', Asset::class);
513+
514+
$rules = array(
515+
'id' => 'required'
516+
);
517+
518+
$validator = \Validator::make($request->all(), $rules);
519+
520+
$asset = Asset::findOrFail($id);
521+
$asset->next_audit_date = $request->input('next_audit_date');
522+
523+
if ($asset->save()) {
524+
$asset->logAudit(request('note'));
525+
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.audit.success')));
526+
}
527+
528+
}
499529
}

app/Http/Controllers/Api/ReportsController.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public function index(Request $request)
3636
->where('item_type','=',"App\\Models\\".ucwords($request->input('item_type')));
3737
}
3838

39+
if ($request->has('action_type')) {
40+
$actionlogs = $actionlogs->where('action_type','=',$request->input('action_type'))->orderBy('created_at', 'desc');
41+
}
42+
3943
$allowed_columns = [
4044
'id',
4145
'created_at'

app/Http/Controllers/AssetsController.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,9 +595,12 @@ public function postCheckin(AssetCheckinRequest $request, $assetId = null, $back
595595
*/
596596
public function show($assetId = null)
597597
{
598+
598599
$asset = Asset::withTrashed()->find($assetId);
599-
$settings = Setting::getSettings();
600600
$this->authorize('view', $asset);
601+
$settings = Setting::getSettings();
602+
$audit_log = Actionlog::where('action_type','=','audit')->where('item_id','=',$assetId)->where('item_type','=',Asset::class)->orderBy('created_at','DESC')->first();
603+
601604

602605
if (isset($asset)) {
603606

@@ -617,7 +620,8 @@ public function show($assetId = null)
617620
'url' => route('qr_code/hardware', $asset->id)
618621
);
619622

620-
return view('hardware/view', compact('asset', 'qr_code', 'settings'))->with('use_currency', $use_currency);
623+
return view('hardware/view', compact('asset', 'qr_code', 'settings'))
624+
->with('use_currency', $use_currency)->with('audit_log',$audit_log);
621625
}
622626

623627
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist', compact('id')));
@@ -1233,4 +1237,29 @@ public function postBulkCheckout(Request $request)
12331237
// Redirect to the asset management page with error
12341238
return redirect()->to("hardware/bulk-checkout")->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($errors);
12351239
}
1240+
1241+
public function audit(Request $request, $id)
1242+
{
1243+
$this->authorize('audit', Asset::class);
1244+
1245+
$dt = Carbon::now()->addMonths(12)->toDateString();
1246+
1247+
$asset = Asset::findOrFail($id);
1248+
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt);
1249+
}
1250+
1251+
public function auditStore(Request $request, $id)
1252+
{
1253+
$this->authorize('audit', Asset::class);
1254+
1255+
$asset = Asset::findOrFail($id);
1256+
$asset->next_audit_date = $request->input('next_audit_date');
1257+
1258+
if ($asset->save()) {
1259+
$asset->logAudit(request('note'));
1260+
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.audit.success'));
1261+
}
1262+
}
1263+
1264+
12361265
}

app/Http/Controllers/ReportsController.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,20 @@ public function exportDeprecationReport()
271271

272272
}
273273

274+
275+
/**
276+
* Displays audit report.
277+
*
278+
* @author [A. Gianotto] [<[email protected]>]
279+
* @since [v4.0]
280+
* @return View
281+
*/
282+
public function audit()
283+
{
284+
return view('reports/audit');
285+
}
286+
287+
274288
/**
275289
* Displays activity report.
276290
*

app/Http/Transformers/ActionlogsTransformer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public function transformActionlog (Actionlog $actionlog)
2929
] : null,
3030
'created_at' => Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
3131
'updated_at' => Helper::getFormattedDateObject($actionlog->updated_at, 'datetime'),
32+
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->item->next_audit_date, 'datetime'): null,
3233
'action_type' => $actionlog->present()->actionType(),
3334
'admin' => ($actionlog->user) ? [
3435
'id' => (int) $actionlog->user->id,

app/Models/Loggable.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use App\Models\CheckoutRequest;
88
use App\Models\User;
99
use App\Notifications\CheckinNotification;
10+
use App\Notifications\AuditNotification;
1011
use App\Notifications\CheckoutNotification;
1112
use Illuminate\Support\Facades\Auth;
1213

@@ -120,6 +121,38 @@ public function logCheckin($target, $note)
120121
return $log;
121122
}
122123

124+
125+
/**
126+
* @author A. Gianotto <[email protected]>
127+
* @since [v4.0]
128+
* @return \App\Models\Actionlog
129+
*/
130+
public function logAudit($note)
131+
{
132+
$log = new Actionlog;
133+
if (static::class == LicenseSeat::class) {
134+
$log->item_type = License::class;
135+
$log->item_id = $this->license_id;
136+
} else {
137+
$log->item_type = static::class;
138+
$log->item_id = $this->id;
139+
}
140+
$log->location_id = null;
141+
$log->note = $note;
142+
$log->user_id = Auth::user()->id;
143+
$log->logaction('audit');
144+
145+
$params = [
146+
'item' => $log->item,
147+
'admin' => $log->user,
148+
'note' => $note
149+
];
150+
Setting::getSettings()->notify(new AuditNotification($params));
151+
152+
return $log;
153+
}
154+
155+
123156
/**
124157
* @author Daniel Meltzer <[email protected]
125158
* @since [v3.5]
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
namespace App\Notifications;
4+
5+
use App\Models\Setting;
6+
use Illuminate\Bus\Queueable;
7+
use Illuminate\Notifications\Messages\SlackMessage;
8+
use Illuminate\Notifications\Notification;
9+
use Illuminate\Notifications\Messages\MailMessage;
10+
11+
class AuditNotification extends Notification
12+
{
13+
use Queueable;
14+
/**
15+
* @var
16+
*/
17+
private $params;
18+
19+
/**
20+
* Create a new notification instance.
21+
*
22+
* @param $params
23+
*/
24+
public function __construct($params)
25+
{
26+
//
27+
$this->params = $params;
28+
}
29+
30+
/**
31+
* Get the notification's delivery channels.
32+
*
33+
* @param mixed $notifiable
34+
* @return array
35+
*/
36+
public function via($notifiable)
37+
{
38+
$notifyBy = [];
39+
if (Setting::getSettings()->slack_endpoint) {
40+
$notifyBy[] = 'slack';
41+
}
42+
43+
return $notifyBy;
44+
}
45+
46+
public function toSlack($notifiable)
47+
{
48+
49+
return (new SlackMessage)
50+
->success()
51+
->content(class_basename(get_class($this->params['item'])) . " Audited")
52+
->attachment(function ($attachment) use ($notifiable) {
53+
$item = $this->params['item'];
54+
$admin_user = $this->params['admin'];
55+
$fields = [
56+
'By' => '<'.$admin_user->present()->viewUrl().'|'.$admin_user->present()->fullName().'>'
57+
];
58+
array_key_exists('note', $this->params) && $fields['Notes'] = $this->params['note'];
59+
60+
$attachment->title($item->name, $item->present()->viewUrl())
61+
->fields($fields);
62+
});
63+
}
64+
/**
65+
* Get the mail representation of the notification.
66+
*
67+
* @param mixed $notifiable
68+
* @return \Illuminate\Notifications\Messages\MailMessage
69+
*/
70+
public function toMail($notifiable)
71+
{
72+
return (new MailMessage)
73+
->line('The introduction to the notification.')
74+
->action('Notification Action', 'https://laravel.com')
75+
->line('Thank you for using our application!');
76+
}
77+
78+
/**
79+
* Get the array representation of the notification.
80+
*
81+
* @param mixed $notifiable
82+
* @return array
83+
*/
84+
public function toArray($notifiable)
85+
{
86+
return [
87+
//
88+
];
89+
}
90+
}

app/Observers/AssetObserver.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public function updating(Asset $asset)
2020

2121

2222
if ((isset($asset->getOriginal()['assigned_to'])) && ($asset->getAttributes()['assigned_to'] == $asset->getOriginal()['assigned_to'])
23+
&& ($asset->getAttributes()['next_audit_date'] == $asset->getOriginal()['next_audit_date'])
2324
&& ($asset->getAttributes()['last_checkout'] == $asset->getOriginal()['last_checkout'])
2425
&& ($asset->getAttributes()['status_id'] == $asset->getOriginal()['status_id']))
2526
{

config/permissions.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@
8585
array(
8686
'permission' => 'assets.audit',
8787
'label' => 'Audit ',
88-
'note' => '',
89-
'display' => false,
88+
'note' => 'Allows the user to mark an asset as physically inventoried.',
89+
'display' => true,
9090
),
9191

9292

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\Schema;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Database\Migrations\Migration;
6+
7+
class AddAuditingTables extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::table('assets', function (Blueprint $table) {
17+
$table->date('next_audit_date')->nullable()->default(NULL);
18+
});
19+
}
20+
21+
/**
22+
* Reverse the migrations.
23+
*
24+
* @return void
25+
*/
26+
public function down()
27+
{
28+
Schema::table('assets', function (Blueprint $table) {
29+
$table->dropColumn('next_audit_date');
30+
});
31+
}
32+
}

0 commit comments

Comments
 (0)