Merge pull request #11172 from snipe/rebased_added_gitkeep_to_to_eula_pdfs

Accept asset/accessory improvements and fixes
This commit is contained in:
snipe 2022-05-23 12:59:01 -07:00 committed by GitHub
commit 8333089278
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 216 additions and 118 deletions

View file

@ -106,87 +106,85 @@ class AcceptanceController extends Controller
Storage::makeDirectory('private_uploads/signatures', 775);
}
$sig_filename = '';
if ($request->filled('signature_output')) {
$sig_filename = 'siglog-'.Str::uuid().'-'.date('Y-m-d-his').'.png';
$data_uri = e($request->input('signature_output'));
$encoded_image = explode(',', $data_uri);
$decoded_image = base64_decode($encoded_image[1]);
$acceptance->stored_eula_file = 'accepted-eula-'.date('Y-m-d-h-i-s').'.pdf';
$path = Storage::put('private_uploads/signatures/'.$sig_filename, (string) $decoded_image);
}
if ($request->input('asset_acceptance') == 'accepted') {
$acceptance->accept($sig_filename);
event(new CheckoutAccepted($acceptance));
$return_msg = trans('admin/users/message.accepted');
} else {
$acceptance->decline($sig_filename);
event(new CheckoutDeclined($acceptance));
$return_msg = trans('admin/users/message.declined');
/**
* Check for the eula-pdfs directory
*/
if (! Storage::exists('private_uploads/eula-pdfs')) {
Storage::makeDirectory('private_uploads/eula-pdfs', 775);
}
$item = $acceptance->checkoutable_type::find($acceptance->checkoutable_id);
$display_model = '';
$pdf_view_route = '';
$pdf_filename = 'accepted-eula-'.date('Y-m-d-h-i-s').'.pdf';
$sig_filename='';
if ($acceptance->checkoutable_type== 'App\Models\Asset') {
$assigned_to = User::find($item->assigned_to);
$asset_model = AssetModel::find($item->model_id);
if ($request->input('asset_acceptance') == 'accepted') {
// The item was accepted, check for a signature
if ($request->filled('signature_output')) {
$sig_filename = 'siglog-'.Str::uuid().'-'.date('Y-m-d-his').'.png';
$data_uri = $request->input('signature_output');
$encoded_image = explode(',', $data_uri);
$decoded_image = base64_decode($encoded_image[1]);
Storage::put('private_uploads/signatures/'.$sig_filename, (string) $decoded_image);
}
// this is horrible
if ($acceptance->checkoutable_type == 'App\Models\Asset') {
$pdf_view_route ='account.accept.accept-asset-eula';
$asset_model = AssetModel::find($item->model_id);
$display_model = $asset_model->name;
$assigned_to = User::find($item->assigned_to)->present()->fullName;
} elseif ($acceptance->checkoutable_type== 'App\Models\Accessory') {
$pdf_view_route ='account.accept.accept-accessory-eula';
$accessory = Accessory::find($item->id);
$display_model = $accessory->name;
$assigned_to = User::find($item->assignedTo);
}
/**
* Gather the data for the PDF. We fire this whether there is a signature required or not,
* since we want the moment-in-time proof of what the EULA was when they accepted it.
*/
$branding_settings = SettingsController::getPDFBranding();
$data = [
'item_tag' => $item->asset_tag,
'item_model' => $asset_model->name,
'item_model' => $display_model,
'item_serial' => $item->serial,
'eula' => $item->getEula(),
'check_out_date' => Carbon::parse($acceptance->created_at)->format($branding_settings->date_display_format),
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format),
'assigned_to' => $assigned_to->first_name . ' ' . $assigned_to->last_name,
'assigned_to' => $assigned_to,
'company_name' => $branding_settings->site_name,
'signature' => storage_path() . '/private_uploads/signatures/' . $sig_filename,
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
'logo' => public_path() . '/uploads/' . $branding_settings->logo,
'date_settings' => $branding_settings->date_display_format,
];
$pdf = Pdf::loadView('account.accept.accept-asset-eula', $data);
Storage::put('private_uploads/eula-pdfs/' . $acceptance->stored_eula_file, $pdf->output());
$a = new Actionlog();
$a->stored_eula = $item->getEula();
$a->stored_eula_file = $acceptance->stored_eula_file;
$a->save();
if ($pdf_view_route!='') {
\Log::debug($pdf_filename.' is the filename, and the route was specified.');
$pdf = Pdf::loadView($pdf_view_route, $data);
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
}
return redirect()->to('account/accept')->with('success', $return_msg);
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename);
event(new CheckoutAccepted($acceptance));
$return_msg = trans('admin/users/message.accepted');
} else {
$acceptance->decline($sig_filename);
event(new CheckoutDeclined($acceptance));
$return_msg = trans('admin/users/message.declined');
}
//
$accessory_user= DB::table('checkout_acceptances')->find($acceptance->assigned_to_id);
$assigned_to = User::find($accessory_user->assigned_to_id);
$accessory_model = Accessory::find($item->id);
$branding_settings = SettingsController::getPDFBranding();
$data = [
'item_tag' => $item->model_number,
'item_model' => $accessory_model->name,
'eula' => $item->getEula(),
'check_out_date' => Carbon::parse($acceptance->created_at)->format($branding_settings->date_display_format),
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format),
// 'assigned_by' => self
'assigned_to' => $assigned_to->first_name . ' ' . $assigned_to->last_name,
'company_name' => $branding_settings->site_name,
'signature' => storage_path() . '/private_uploads/signatures/' . $sig_filename,
'logo' => public_path() . '/uploads/' . $branding_settings->logo,
'date_settings' => $branding_settings->date_display_format,
];
$pdf = Pdf::loadView('account.accept.accept-accessory-eula', $data);
Storage::put('private_uploads/eula-pdfs/' . $acceptance->stored_eula_file, $pdf->output());
$a = new Actionlog();
$a->stored_eula = $item->getEula();
$a->stored_eula_file = $acceptance->stored_eula_file;
$a->save();
return redirect()->to('account/accept')->with('success', $return_msg);
}
}

View file

@ -52,7 +52,6 @@ class ReportsController extends Controller
'accept_signature',
'action_type',
'note',
'stored_eula_file',
];
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';

View file

@ -98,9 +98,6 @@ class AssetCheckinController extends Controller
}
$asset->location_id = $asset->rtd_location_id;
\Log::debug('After Location ID: '.$asset->location_id);
\Log::debug('After RTD Location ID: '.$asset->rtd_location_id);
if ($request->filled('location_id')) {
\Log::debug('NEW Location ID: '.$request->get('location_id'));

View file

@ -59,9 +59,14 @@ class ActionlogsTransformer
$array = [
'id' => (int) $actionlog->id,
'icon' => $icon,
'file' => ($actionlog->filename!='') ?
'file' => ($actionlog->filename!='')
?
[
'url' => route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]),
'url' => ($actionlog->present()->actionType()=='accepted')
?
route('log.storedeula.download', ['filename' => $actionlog->filename])
:
route('show/assetfile', ['assetId' => $actionlog->id, 'fileId' => $actionlog->id]),
'filename' => $actionlog->filename,
'inlineable' => (bool) Helper::show_file_inline($actionlog->filename),
] : null,
@ -96,7 +101,6 @@ class ActionlogsTransformer
'signature_file' => ($actionlog->accept_signature) ? route('log.signature.view', ['filename' => $actionlog->accept_signature ]) : null,
'log_meta' => ((isset($clean_meta)) && (is_array($clean_meta))) ? $clean_meta: null,
'action_date' => ($actionlog->action_date) ? Helper::getFormattedDateObject($actionlog->action_date, 'datetime'): Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
'stored_eula_file' => ($actionlog->stored_eula_file) ? route('log.storedeula.download', ['filename' => $actionlog->stored_eula_file]) : null,
];
//\Log::info("Clean Meta is: ".print_r($clean_meta,true));

View file

@ -24,10 +24,14 @@ use Illuminate\Support\Facades\Notification;
class CheckoutableListener
{
/**
* Notify the user about the checked out checkoutable
* Notify the user about the checked out checkoutable and add a record to the
* checkout_requests table.
*/
public function onCheckedOut($event)
{
\Log::debug('onCheckedOut in the Checkoutable listener fired');
/**
* When the item wasn't checked out to a user, we can't send notifications
*/
@ -58,14 +62,12 @@ class CheckoutableListener
*/
public function onCheckedIn($event)
{
\Log::debug('checkin fired');
\Log::debug('onCheckedIn in the Checkoutable listener fired');
/**
* When the item wasn't checked out to a user, we can't send notifications
*/
if (! $event->checkedOutTo instanceof User) {
\Log::debug('checked out to not a user');
return;
}
@ -81,16 +83,14 @@ class CheckoutableListener
$acceptance->delete();
}
}
\Log::debug('checked out to a user');
// Use default locale
if (! $event->checkedOutTo->locale) {
\Log::debug('Use default settings locale');
Notification::locale(Setting::getSettings()->locale)->send(
$this->getNotifiables($event),
$this->getCheckinNotification($event)
);
} else {
\Log::debug('Use user locale? I do not think this works as expected yet');
// \Log::debug(print_r($this->getNotifiables($event), true));
Notification::send(
$this->getNotifiables($event),
$this->getCheckinNotification($event)
@ -151,10 +151,6 @@ class CheckoutableListener
private function getCheckinNotification($event)
{
// $model = get_class($event->checkoutable);
$notificationClass = null;
switch (get_class($event->checkoutable)) {

View file

@ -22,24 +22,44 @@ use App\Models\LicenseSeat;
class LogListener
{
/**
* These onBlah methods are used by the subscribe() method further down in this file.
* This one creates an action_logs entry for the checkin
* @param CheckoutableCheckedIn $event
* @return void
*
*/
public function onCheckoutableCheckedIn(CheckoutableCheckedIn $event)
{
$event->checkoutable->logCheckin($event->checkedOutTo, $event->note, $event->action_date);
}
/**
* These onBlah methods are used by the subscribe() method further down in this file.
* This one creates an action_logs entry for the checkout
*
* @param CheckoutableCheckedOut $event
* @return void
*
*/
public function onCheckoutableCheckedOut(CheckoutableCheckedOut $event)
{
$event->checkoutable->logCheckout($event->note, $event->checkedOutTo, $event->checkoutable->last_checkout);
}
/**
* These onBlah methods are used by the subscribe() method further down in this file.
* This creates the entry in the action_logs table for the accept/decline action
*/
public function onCheckoutAccepted(CheckoutAccepted $event)
{
\Log::error('event passed to the onCheckoutAccepted listener:');
$logaction = new Actionlog();
$logaction->item()->associate($event->acceptance->checkoutable);
$logaction->target()->associate($event->acceptance->assignedTo);
$logaction->accept_signature = $event->acceptance->signature_filename;
$logaction->stored_eula_file = $event->acceptance->stored_eula_file;
$logaction->filename = $event->acceptance->stored_eula_file;
$logaction->action_type = 'accepted';
// TODO: log the actual license seat that was checked out
@ -47,6 +67,7 @@ class LogListener
$logaction->item()->associate($event->acceptance->checkoutable->license);
}
\Log::debug('New onCheckoutAccepted Listener fired. logaction: '.print_r($logaction, true));
$logaction->save();
}

View file

@ -25,7 +25,7 @@ class Actionlog extends SnipeModel
protected $table = 'action_logs';
public $timestamps = true;
protected $fillable = ['created_at', 'item_type', 'user_id', 'item_id', 'action_type', 'note', 'target_id', 'target_type', 'stored_eula', 'stored_eula_file'];
protected $fillable = ['created_at', 'item_type', 'user_id', 'item_id', 'action_type', 'note', 'target_id', 'target_type', 'stored_eula'];
use Searchable;

View file

@ -57,20 +57,24 @@ class CheckoutAcceptance extends Model
}
/**
* Accept the checkout acceptance
* Add a record to the checkout_acceptance table ONLY.
* Do not add stuff here that doesn't have a corresponding column in the
* checkout_acceptances table or you'll get an error.
*
* @param string $signature_filename
*/
public function accept($signature_filename)
public function accept($signature_filename, $eula = null, $filename = null)
{
$this->accepted_at = now();
$this->signature_filename = $signature_filename;
$this->stored_eula = $eula;
$this->stored_eula_file = $filename;
$this->save();
/**
* Update state for the checked out item
*/
$this->checkoutable->acceptedCheckout($this->assignedTo, $signature_filename);
$this->checkoutable->acceptedCheckout($this->assignedTo, $signature_filename, $filename);
}
/**

View file

@ -17,8 +17,9 @@ trait Acceptable
* @param User $acceptedBy
* @param string $signature
*/
public function acceptedCheckout(User $acceptedBy, $signature)
public function acceptedCheckout(User $acceptedBy, $signature, $filename = null)
{
\Log::debug('acceptedCheckout in Acceptable trait fired, tho it doesn\'t do anything?');
}
/**

View file

@ -54,7 +54,6 @@ class CheckinAssetNotification extends Notification
* has the corresponding checkbox checked.
*/
if ($this->item->checkin_email() && $this->target instanceof User && $this->target->email != '') {
\Log::debug('use email');
$notifyBy[] = 'mail';
}

View file

@ -36,6 +36,11 @@ class SettingsServiceProvider extends ServiceProvider
// Model paths and URLs
\App::singleton('eula_pdf_path', function () {
return 'eula_pdf_path/';
});
\App::singleton('assets_upload_path', function () {
return 'assets/';
});

View file

@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use App\Models\Actionlog;
class RemoveStoredEulaField extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$actionlog_eulas = Actionlog::whereNotNull('stored_eula_file')->get();
foreach ($actionlog_eulas as $eula_file) {
$eula_file->filename = $eula_file->stored_eula_file;
$eula_file->save();
}
$actionlog_bad_action_type = Actionlog::where('item_id', '=', 0)->whereNull('target_type')->whereNull('action_type')->whereNull('target_type')->get();
foreach ($actionlog_bad_action_type as $bad_action_type) {
$bad_action_type->delete();
}
Schema::table('action_logs', function (Blueprint $table) {
$table->dropColumn('stored_eula_file');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('action_logs', function (Blueprint $table) {
$table->string('stored_eula_file')->nullable()->default(null);
});
}
}

View file

@ -4,10 +4,16 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style>
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 11px;
}
</style>
</head>
<body>
@if ($signature)
@if ($logo)
<center>
<img src="{{ $logo }}">
<p>{{$company_name}}</p>
@ -15,22 +21,27 @@
@endif
<br>
<p>Date: {{ date($date_settings) }} </p><br>
<p>Asset Tag: {{ $item_tag }}</p>
<p>Asset Model: {{ $item_model }}</p>
<p>
{{ trans('general.date') }}: {{ date($date_settings) }} <br>
{{ trans('general.asset_model') }}: {{ $item_model }}<br>
</p>
@if ($eula)
<hr>
{!! $eula !!}
<hr>
@endif
<br>
<p>Assigned on: {{$check_out_date}}</p>
<p>Accepted on: {{$accepted_date}}</p>
<p>Assigned to: {{$assigned_to}}</p>
@if ($signature)
<center>
<img src="{{ $signature }}" style="max-width: 50%">
</center>
<p>
Assigned on: {{$check_out_date}}<br>
Assigned to: {{$assigned_to}}<br>
Accepted on: {{$accepted_date}}
</p>
@if ($signature!='')
<img src="{{ $signature }}" style="max-width: 600px; border-bottom: black solid 1px;">
@endif
</body>
</html>

View file

@ -4,10 +4,16 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style>
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 11px;
}
</style>
</head>
<body>
@if ($signature)
@if ($logo)
<center>
<img src="{{ $logo }}">
<p>{{$company_name}}</p>
@ -15,23 +21,30 @@
@endif
<br>
<p>Date: {{ date($date_settings) }} </p><br>
<p>Asset Tag: {{ $item_tag }}</p>
<p>Asset Model: {{ $item_model }}</p>
<p>Asset Serial: {{ $item_serial }}</p><br>
<p>
{{ trans('general.date') }}: {{ date($date_settings) }} <br>
{{ trans('general.asset_tag') }}: {{ $item_tag }}<br>
{{ trans('general.asset_model') }}: {{ $item_model }}<br>
{{ trans('admin/hardware/form.serial') }}: {{ $item_serial }}
</p>
@if ($eula)
<hr>
{!! $eula !!}
<hr>
@endif
<br>
<p>Assigned on: {{$check_out_date}}</p>
<p>Accepted on: {{$accepted_date}}</p>
<p>Assigned to: {{$assigned_to}}</p>
@if ($signature)
<center>
<img src="{{ $signature }}" style="max-width: 50%">
</center>
<p>
Assigned on: {{$check_out_date}}<br>
Assigned to: {{$assigned_to}}<br>
Accepted on: {{$accepted_date}}
</p>
@if ($signature!='')
<img src="{{ $signature }}" style="max-width: 600px; border-bottom: black solid 1px;">
@endif
</body>
</html>

View file

@ -46,14 +46,14 @@
<div class="col-md-12">
<div class="radio">
<label>
<input type="radio" name="asset_acceptance" id="accepted" value="accepted">
<input type="radio" name="asset_acceptance" id="accepted" value="accepted" class="minimal">
{{ trans('general.i_accept') }}
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="asset_acceptance" id="declined" value="declined">
<input type="radio" name="asset_acceptance" id="declined" value="declined" class="minimal">
{{ trans('general.i_decline') }}
</label>
</div>
@ -77,7 +77,7 @@
<input type="hidden" name="signature_output" id="signature_output">
</div>
<div class="col-md-12 col-sm-12 col-lg-12 col-xs-12 text-center">
<button type="button" class="btn btn-sm btn-default clear" data-action="clear" id="clear_button">{{ trans('general.clear_signature') }}</button>
<button type="button" class="btn btn-sm btn-primary clear" data-action="clear" id="clear_button">{{ trans('general.clear_signature') }}</button>
</div>
</div>
</div> <!-- .col-md-12.text-center-->

View file

@ -1100,8 +1100,10 @@
<th class="col-sm-2" data-visible="true" data-field="item" data-formatter="polymorphicItemFormatter">{{ trans('general.item') }}</th>
<th class="col-sm-2" data-visible="true" data-field="target" data-formatter="polymorphicItemFormatter">{{ trans('general.target') }}</th>
<th class="col-sm-2" data-field="note">{{ trans('general.notes') }}</th>
<th class="col-sm-1" data-field="stored_eula_file" data-visible="true" data-formatter="downloadFormatter">{{ trans('general.accept_eula') }}</th>
<th class="col-md-3" data-visible="false" data-field="file" data-visible="false" data-formatter="fileUploadFormatter">{{ trans('general.download') }}</th>
@if ($snipeSettings->require_accept_signature=='1')
<th class="col-md-3" data-field="signature_file" data-visible="false" data-formatter="imageFormatter">{{ trans('general.signature') }}</th>
@endif
<th class="col-md-3" data-visible="false" data-field="file" data-visible="false" data-formatter="fileUploadFormatter">{{ trans('general.download') }}</th>
<th class="col-sm-2" data-field="log_meta" data-visible="true" data-formatter="changeLogFormatter">{{ trans('admin/hardware/table.changed')}}</th>
</tr>
</thead>

View file

@ -125,7 +125,7 @@ Route::group(['middleware' => 'auth'], function () {
[ActionlogController::class, 'displaySig']
)->name('log.signature.view');
Route::get(
'stored-eula-file/{filename}/',
'stored-eula-file/{filename}',
[ActionlogController::class, 'getStoredEula']
)->name('log.storedeula.download');
});