Merge pull request #11650 from snipe/fixes/6877_add_notes_to_consumables

Fixed #6877 - Added notes to consumables, components on checkout
This commit is contained in:
snipe 2022-08-10 16:11:08 -07:00 committed by GitHub
commit c77d763f05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 98 additions and 23 deletions

View file

@ -246,7 +246,8 @@ class ComponentsController extends Controller
'created_at' => \Carbon::now(),
'assigned_qty' => $request->get('assigned_qty', 1),
'user_id' => \Auth::id(),
'asset_id' => $request->get('assigned_to')
'asset_id' => $request->get('assigned_to'),
'note' => $request->get('note'),
]);
$component->logCheckout($request->input('note'), $asset);

View file

@ -230,7 +230,8 @@ class ConsumablesController extends Controller
$rows[] = [
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : '',
'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null,
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : null,
];
}
@ -273,6 +274,7 @@ class ConsumablesController extends Controller
'consumable_id' => $consumable->id,
'user_id' => $user->id,
'assigned_to' => $assigned_to,
'note' => $request->input('note'),
]);
// Log checkout event

View file

@ -87,6 +87,7 @@ class ComponentCheckoutController extends Controller
'created_at' => date('Y-m-d H:i:s'),
'assigned_qty' => $request->input('assigned_qty'),
'asset_id' => $asset_id,
'note' => $request->input('note'),
]);
event(new CheckoutableCheckedOut($component, $asset, Auth::user(), $request->input('note')));

View file

@ -56,7 +56,7 @@ class ConsumableCheckoutController extends Controller
// Check if the user exists
if (is_null($user = User::find($assigned_to))) {
// Redirect to the consumable management page with error
return redirect()->route('consumables.checkout.show', $consumable)->with('error', trans('admin/consumables/message.checkout.user_does_not_exist'));
return redirect()->route('consumables.checkout.show', $consumable)->with('error', trans('admin/consumables/message.checkout.user_does_not_exist'))->withInput();
}
// Update the consumable data
@ -66,6 +66,7 @@ class ConsumableCheckoutController extends Controller
'consumable_id' => $consumable->id,
'user_id' => $admin_user->id,
'assigned_to' => e($request->input('assigned_to')),
'note' => $request->input('note'),
]);
event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));

View file

@ -26,6 +26,7 @@ class ComponentsAssetsTransformer
'created_at' => $asset->created_at->format('Y-m-d'),
'qty' => $asset->components()->count(),
'user_can_checkout' => $asset->availableForCheckout(),
'note' => e($asset->note),
];
$permissions_array['available_actions'] = [

View file

@ -71,6 +71,7 @@ class ComponentsTransformer
'id' => (int) $asset->id,
'name' => e($asset->model->present()->name).' '.e($asset->present()->name),
'qty' => $asset->pivot->assigned_qty,
'note' => $asset->pivot->note,
'type' => 'asset',
'created_at' => Helper::getFormattedDateObject($asset->pivot->created_at, 'datetime'),
'available_actions' => ['checkin' => true],

View file

@ -109,7 +109,7 @@ class Component extends SnipeModel
*/
public function assets()
{
return $this->belongsToMany(\App\Models\Asset::class, 'components_assets')->withPivot('id', 'assigned_qty', 'created_at', 'user_id');
return $this->belongsToMany(\App\Models\Asset::class, 'components_assets')->withPivot('id', 'assigned_qty', 'created_at', 'user_id', 'note');
}
/**

View file

@ -308,7 +308,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
*/
public function consumables()
{
return $this->belongsToMany(\App\Models\Consumable::class, 'consumables_users', 'assigned_to', 'consumable_id')->withPivot('id','created_at')->withTrashed();
return $this->belongsToMany(\App\Models\Consumable::class, 'consumables_users', 'assigned_to', 'consumable_id')->withPivot('id','created_at','note')->withTrashed();
}
/**

View file

@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddNotesDenormToConsumablesUsers extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('consumables_users', function (Blueprint $table) {
$table->text('note')->nullable()->default(null);
});
Schema::table('components_assets', function (Blueprint $table) {
$table->text('note')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('consumables_users', function (Blueprint $table) {
if (Schema::hasColumn('consumables_users', 'note')) {
$table->dropColumn('note');
}
});
Schema::table('components_assets', function (Blueprint $table) {
if (Schema::hasColumn('components_assets', 'note')) {
$table->dropColumn('note');
}
});
}
}

View file

@ -171,7 +171,7 @@
@can('checkout', \App\Models\Accessory::class)
<div class="row">
<div class="col-md-12 text-center">
<a href="{{ route('accessories.checkout.show', $accessory->id) }}" style="margin-right:5px;" class="btn btn-primary btn-sm" {{ (($accessory->numRemaining() > 0 ) ? '' : ' disabled') }}>{{ trans('general.checkout') }}</a>
<a href="{{ route('accessories.checkout.show', $accessory->id) }}" style="margin-right:5px; width:100%" class="btn btn-primary btn-sm" {{ (($accessory->numRemaining() > 0 ) ? '' : ' disabled') }}>{{ trans('general.checkout') }}</a>
</div>
</div>
@endcan

View file

@ -47,6 +47,15 @@
</div>
</div>
<!-- Note -->
<div class="form-group {{ $errors->has('note') ? 'error' : '' }}">
<label for="note" class="col-md-3 control-label">{{ trans('admin/hardware/form.notes') }}</label>
<div class="col-md-7">
<textarea class="col-md-6 form-control" id="note" name="note">{{ old('note', $component->note) }}</textarea>
{!! $errors->first('note', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>
</div> <!-- .BOX-BODY-->
<div class="box-footer">

View file

@ -87,6 +87,9 @@
<th data-searchable="false" data-sortable="false" data-field="qty">
{{ trans('general.qty') }}
</th>
<th data-searchable="false" data-sortable="false" data-field="note">
{{ trans('general.notes') }}
</th>
<th data-searchable="false" data-sortable="false" data-field="created_at" data-formatter="dateDisplayFormatter">
{{ trans('general.date') }}
</th>

View file

@ -70,13 +70,13 @@
<div class="form-group {{ $errors->has('note') ? 'error' : '' }}">
<label for="note" class="col-md-3 control-label">{{ trans('admin/hardware/form.notes') }}</label>
<div class="col-md-7">
<textarea class="col-md-6 form-control" id="note" name="note">{{ old('note', $consumable->note) }}</textarea>
<textarea class="col-md-6 form-control" name="note">{{ old('note') }}</textarea>
{!! $errors->first('note', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>
</div> <!-- .box-body -->
<div class="box-footer">
<a class="btn btn-link" href="{{ URL::previous() }}">{{ trans('button.cancel') }}</a>
<a class="btn btn-link" href="{{ route('consumables.show', ['consumable'=> $consumable->id]) }}">{{ trans('button.cancel') }}</a>
<button type="submit" class="btn btn-primary pull-right"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('general.checkout') }}</button>
</div>
</div>

View file

@ -55,6 +55,7 @@
<tr>
<th data-searchable="false" data-sortable="false" data-field="name">{{ trans('general.user') }}</th>
<th data-searchable="false" data-sortable="false" data-field="created_at" data-formatter="dateDisplayFormatter">{{ trans('general.date') }}</th>
<th data-searchable="false" data-sortable="false" data-field="note">{{ trans('general.notes') }}</th>
<th data-searchable="false" data-sortable="false" data-field="admin">{{ trans('general.admin') }}</th>
</tr>
</thead>
@ -76,21 +77,21 @@
@if ($consumable->image!='')
<div class="col-md-12 text-center" style="padding-bottom: 15px;">
<div class="col-md-12 text-center">
<a href="{{ Storage::disk('public')->url('consumables/'.e($consumable->image)) }}" data-toggle="lightbox">
<img src="{{ Storage::disk('public')->url('consumables/'.e($consumable->image)) }}" class="img-responsive img-thumbnail" alt="{{ $consumable->name }}"></a>
</div>
@endif
@if ($consumable->purchase_date)
<div class="col-md-12" style="padding-bottom: 15px;">
<div class="col-md-12">
<strong>{{ trans('general.purchase_date') }}: </strong>
{{ Helper::getFormattedDateObject($consumable->purchase_date, 'date', false) }}
</div>
@endif
@if ($consumable->purchase_cost)
<div class="col-md-12" style="padding-bottom: 15px;">
<div class="col-md-12">
<strong>{{ trans('general.purchase_cost') }}:</strong>
{{ $snipeSettings->default_currency }}
{{ Helper::formatCurrencyOutput($consumable->purchase_cost) }}
@ -98,28 +99,28 @@
@endif
@if ($consumable->item_no)
<div class="col-md-12" style="padding-bottom: 15px;">
<div class="col-md-12">
<strong>{{ trans('admin/consumables/general.item_no') }}:</strong>
{{ $consumable->item_no }}
</div>
@endif
@if ($consumable->model_number)
<div class="col-md-12" style="padding-bottom: 15px;">
<div class="col-md-12">
<strong>{{ trans('general.model_no') }}:</strong>
{{ $consumable->model_number }}
</div>
@endif
@if ($consumable->manufacturer)
<div class="col-md-12" style="padding-bottom: 15px;">
<div class="col-md-12">
<strong>{{ trans('general.manufacturer') }}:</strong>
<a href="{{ route('manufacturers.show', $consumable->manufacturer->id) }}">{{ $consumable->manufacturer->name }}</a>
</div>
@endif
@if ($consumable->order_number)
<div class="col-md-12" style="padding-bottom: 15px;">
<div class="col-md-12">
<strong>{{ trans('general.order_number') }}:</strong>
{{ $consumable->order_number }}
</div>
@ -128,13 +129,13 @@
@can('checkout', \App\Models\Consumable::class)
<div class="col-md-12">
<br><br>
@if ($consumable->numRemaining() > 0)
<a href="{{ route('consumables.checkout.show', $consumable->id) }}" style="padding-bottom:5px;" class="btn btn-primary btn-sm">
<a href="{{ route('consumables.checkout.show', $consumable->id) }}" style="margin-bottom:10px; width:100%" class="btn btn-primary btn-sm">
{{ trans('general.checkout') }}
</a>
@else
<button style="padding-bottom:5px;" class="btn btn-primary btn-sm disabled">
<button style="margin-bottom:10px; width:100%"" class="btn btn-primary btn-sm disabled">
{{ trans('general.checkout') }}
</button>
@endif
@ -146,7 +147,7 @@
<div class="col-md-12">
<strong>
{{ trans('general.notes') }}
{{ trans('general.notes') }}:
</strong>
</div>
<div class="col-md-12">

View file

@ -763,9 +763,10 @@
}'>
<thead>
<tr>
<th class="col-md-6">{{ trans('general.name') }}</th>
<th class="col-md-3">{{ trans('general.name') }}</th>
<th class="col-md-2" data-footer-formatter="sumFormatter" data-fieldname="purchase_cost">{{ trans('general.purchase_cost') }}</th>
<th class="col-md-4">{{ trans('general.date') }}</th>
<th class="col-md-2">{{ trans('general.date') }}</th>
<th class="col-md-5">{{ trans('general.notes') }}</th>
</tr>
</thead>
<tbody>
@ -775,7 +776,8 @@
<td>
{!! Helper::formatCurrencyOutput($consumable->purchase_cost) !!}
</td>
<td>{{ $consumable->pivot->created_at }}</td>
<td>{{ Helper::getFormattedDateObject($consumable->pivot->created_at, 'datetime', false) }}</td>
<td>{{ $consumable->pivot->note }}</td>
</tr>
@endforeach
</tbody>

View file

@ -280,13 +280,22 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:api']], functi
]
)->name('api.consumables.selectlist');
Route::get('view/{id}/users',
Route::get('{id}/users',
[
Api\ConsumablesController::class,
'getDataView'
]
)->name('api.consumables.showUsers');
// This is LEGACY endpoint URL and should be removed in the next major release
Route::get('view/{id}/users',
[
Api\ConsumablesController::class,
'getDataView'
]
)->name('api.consumables.showUsers');
Route::post('{consumable}/checkout',
[
Api\ConsumablesController::class,