Save Progress.

This commit is contained in:
Daniel Meltzer 2016-12-27 19:24:41 -05:00
parent 13cf11368f
commit d262aec4c3
13 changed files with 136 additions and 42 deletions

View file

@ -68,7 +68,7 @@ class SendExpirationAlerts extends Command
$asset_data['email_content'] .= '<td>'.e($asset->present()->warrantee_expires()).'</td>'; $asset_data['email_content'] .= '<td>'.e($asset->present()->warrantee_expires()).'</td>';
$asset_data['email_content'] .= '<td>'.$difference.' '.trans('mail.days').'</td>'; $asset_data['email_content'] .= '<td>'.$difference.' '.trans('mail.days').'</td>';
$asset_data['email_content'] .= '<td>'.($asset->supplier ? e($asset->supplier->name) : '').'</td>'; $asset_data['email_content'] .= '<td>'.($asset->supplier ? e($asset->supplier->name) : '').'</td>';
$asset_data['email_content'] .= '<td>'.($asset->assigneduser ? e($asset->assigneduser->present()->fullName()) : '').'</td>'; $asset_data['email_content'] .= '<td>'.($asset->assignedTo ? e($asset->assignedTo->present()->name()) : '').'</td>';
$asset_data['email_content'] .= '</tr>'; $asset_data['email_content'] .= '</tr>';
} }

View file

@ -416,7 +416,10 @@ class AssetsController extends Controller
$this->authorize('checkout', $asset); $this->authorize('checkout', $asset);
// Get the dropdown of users and then pass it to the checkout view // Get the dropdown of users and then pass it to the checkout view
return View::make('hardware/checkout', compact('asset'))->with('users_list', Helper::usersList()); return View::make('hardware/checkout', compact('asset'))
->with('users_list', Helper::usersList())
->with('assets_list', Helper::assetsList())
->with('locations_list', Helper::locationsList());
} }
@ -431,7 +434,6 @@ class AssetsController extends Controller
*/ */
public function postCheckout(AssetCheckoutRequest $request, $assetId) public function postCheckout(AssetCheckoutRequest $request, $assetId)
{ {
// Check if the asset exists // Check if the asset exists
if (!$asset = Asset::find($assetId)) { if (!$asset = Asset::find($assetId)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist')); return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
@ -440,7 +442,14 @@ class AssetsController extends Controller
} }
$this->authorize('checkout', $asset); $this->authorize('checkout', $asset);
$user = User::find(Input::get('assigned_to')); if(request('assigned_user')) {
$target = User::find(request('assigned_user'));
} elseif(request('assigned_asset')) {
$target = Asset::find(request('assigned_asset'));
} elseif(request('assigned_location')) {
$target = Location::find(request('assigned_location'));
}
// $user = User::find(Input::get('assigned_to'));
$admin = Auth::user(); $admin = Auth::user();
if ((Input::has('checkout_at')) && (Input::get('checkout_at')!= date("Y-m-d"))) { if ((Input::has('checkout_at')) && (Input::get('checkout_at')!= date("Y-m-d"))) {
@ -454,7 +463,7 @@ class AssetsController extends Controller
} else { } else {
$expected_checkin = ''; $expected_checkin = '';
} }
if ($asset->checkOutToUser($user, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), e(Input::get('name')))) { if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), e(Input::get('name')))) {
// Redirect to the new asset page // Redirect to the new asset page
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.checkout.success')); return redirect()->to("hardware")->with('success', trans('admin/hardware/message.checkout.success'));
} }
@ -518,6 +527,7 @@ class AssetsController extends Controller
$asset->expected_checkin = null; $asset->expected_checkin = null;
$asset->last_checkout = null; $asset->last_checkout = null;
$asset->assigned_to = null; $asset->assigned_to = null;
$asset->assignedTo()->disassociate($asset);
$asset->accepted = null; $asset->accepted = null;
$asset->name = e(Input::get('name')); $asset->name = e(Input::get('name'));

View file

@ -121,7 +121,7 @@ class ReportsController extends Controller
// Open output stream // Open output stream
$handle = fopen('php://output', 'w'); $handle = fopen('php://output', 'w');
Asset::with('assigneduser', 'assetloc','defaultLoc','assigneduser.userloc','model','supplier','assetstatus','model.manufacturer')->orderBy('created_at', 'DESC')->chunk(500, function($assets) use($handle, $customfields) { Asset::with('assignedTo', 'assetLoc','defaultLoc','assigneduser.userloc','model','supplier','assetstatus','model.manufacturer')->orderBy('created_at', 'DESC')->chunk(500, function($assets) use($handle, $customfields) {
$headers=[ $headers=[
trans('general.company'), trans('general.company'),
trans('admin/hardware/table.asset_tag'), trans('admin/hardware/table.asset_tag'),
@ -162,8 +162,7 @@ class ReportsController extends Controller
($asset->supplier) ? e($asset->supplier->name) : '', ($asset->supplier) ? e($asset->supplier->name) : '',
($asset->assigneduser) ? e($asset->assigneduser->present()->fullName()) : '', ($asset->assigneduser) ? e($asset->assigneduser->present()->fullName()) : '',
($asset->last_checkout!='') ? e($asset->last_checkout) : '', ($asset->last_checkout!='') ? e($asset->last_checkout) : '',
($asset->assigneduser && $asset->assigneduser->userloc!='') ? e($asset->assetLoc->present()->name()),
e($asset->assigneduser->userloc->name) : ( ($asset->defaultLoc!='') ? e($asset->defaultLoc->name) : ''),
($asset->notes) ? e($asset->notes) : '', ($asset->notes) ? e($asset->notes) : '',
]; ];
foreach($customfields as $field) { foreach($customfields as $field) {
@ -244,15 +243,13 @@ class ReportsController extends Controller
$row[] = e($asset->name); $row[] = e($asset->name);
$row[] = e($asset->serial); $row[] = e($asset->serial);
if ($asset->assigned_to > 0) { if ($target = $asset->assignedTo) {
$user = User::find($asset->assigned_to); $row[] = e($target->present()->name());
$row[] = e($user->present()->fullName());
} else { } else {
$row[] = ''; // Empty string if unassigned $row[] = ''; // Empty string if unassigned
} }
if (( $asset->assigned_to > 0 ) && ( $asset->assigneduser->location_id > 0 )) { if (( $asset->assigned_to > 0 ) && ( $location = $asset->assetLoc )) {
$location = Location::find($asset->assigneduser->location_id);
if ($location->city) { if ($location->city) {
$row[] = e($location->city) . ', ' . e($location->state); $row[] = e($location->city) . ', ' . e($location->state);
} elseif ($location->name) { } elseif ($location->name) {

View file

@ -24,7 +24,9 @@ class AssetCheckoutRequest extends Request
public function rules() public function rules()
{ {
return [ return [
"assigned_to" => 'required', "assigned_user" => 'required_without_all:assigned_asset,assigned_location',
"assigned_asset" => 'required_without_all:assigned_user,assigned_location',
"assigned_location" => 'required_without_all:assigned_user,assigned_asset',
]; ];
} }
} }

View file

@ -22,6 +22,9 @@ class Asset extends Depreciable
use Loggable, Requestable, Presentable; use Loggable, Requestable, Presentable;
use SoftDeletes; use SoftDeletes;
const LOCATION = 'location';
const ASSET = 'asset';
const USER = 'user';
/** /**
* The database table used by the model. * The database table used by the model.
* *
@ -91,9 +94,9 @@ class Asset extends Depreciable
* @param null $name * @param null $name
* @return bool * @return bool
*/ */
public function checkOutToUser($user, $admin, $checkout_at = null, $expected_checkin = null, $note = null, $name = null) public function checkOut($target, $admin, $checkout_at = null, $expected_checkin = null, $note = null, $name = null)
{ {
if (!$user) { if (!$target) {
return false; return false;
} }
@ -103,7 +106,8 @@ class Asset extends Depreciable
$this->last_checkout = $checkout_at; $this->last_checkout = $checkout_at;
$this->assigneduser()->associate($user); $this->assignedTo()->associate($target);
if($name != null) { if($name != null) {
$this->name = $name; $this->name = $name;
@ -113,8 +117,6 @@ class Asset extends Depreciable
$this->accepted="pending"; $this->accepted="pending";
} }
if ($this->save()) { if ($this->save()) {
$log = $this->logCheckout($note); $log = $this->logCheckout($note);
if ((($this->requireAcceptance()=='1') || ($this->getEula())) && ($user->email!='')) { if ((($this->requireAcceptance()=='1') || ($this->getEula())) && ($user->email!='')) {
@ -150,7 +152,6 @@ class Asset extends Depreciable
} }
public function getDetailedNameAttribute() public function getDetailedNameAttribute()
{ {
if ($this->assignedUser) { if ($this->assignedUser) {
@ -209,18 +210,41 @@ class Asset extends Depreciable
->withTrashed(); ->withTrashed();
} }
public function assignedTo()
{
return $this->morphTo('assigned', 'assigned_type', 'assigned_to');
}
public function assignedAssets()
{
return $this->morphMany('App\Models\Asset', 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
}
/** /**
* Get the asset's location based on the assigned user * Get the asset's location based on the assigned user
**/ **/
public function assetloc() public function assetLoc()
{ {
if ($this->assigneduser) { if(!empty($this->assignedType())) {
return $this->assigneduser->userloc(); if ($this->assignedType() == self::ASSET) {
} else { return $this->assignedTo->assetloc(); // Recurse until we have a final location
return $this->belongsTo('\App\Models\Location', 'rtd_location_id'); } elseif ($this->assignedType() == self::LOCATION) {
return $this->assignedTo();
}
// Default to User
// var_dump($this);
if(!$this->assignedTo) {
dd($this);
}
return $this->assignedTo->userLoc();
} }
return $this->defaultLoc();
} }
public function assignedType()
{
return strtolower(class_basename($this->assigned_type));
}
/** /**
* Get the asset's location based on default RTD location * Get the asset's location based on default RTD location
**/ **/

View file

@ -55,9 +55,9 @@ class Location extends SnipeModel
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\User', 'location_id', 'assigned_to', 'id'); return $this->hasManyThrough('\App\Models\Asset', '\App\Models\User', 'location_id', 'assigned_to', 'id');
} }
public function assignedassets() public function locationAssets()
{ {
return $this->hasMany('\App\Models\Asset', 'rtd_location_id'); return $this->hasMany('\App\Models\Asset', 'rtd_location_id')->orHas('assignedAssets');
} }
public function parent() public function parent()
@ -70,6 +70,12 @@ class Location extends SnipeModel
return $this->hasMany('\App\Models\Location', 'parent_id'); return $this->hasMany('\App\Models\Location', 'parent_id');
} }
public function assignedAssets()
{
return $this->morphMany('App\Models\Asset', 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
// return $this->hasMany('\App\Models\Asset', 'assigned_to')->withTrashed();
}
public static function getLocationHierarchy($locations, $parent_id = null) public static function getLocationHierarchy($locations, $parent_id = null)
{ {

View file

@ -45,7 +45,7 @@ trait Loggable
$log->user_id = Auth::user()->id; $log->user_id = Auth::user()->id;
if (!is_null($this->asset_id) || isset($target)) { if (!is_null($this->asset_id) || isset($target)) {
$log->target_type = Asset::class; $log->target_type = $this->assigned_type;
$log->target_id = $this->asset_id; $log->target_id = $this->asset_id;
} else if (!is_null($this->assigned_to)) { } else if (!is_null($this->assigned_to)) {
$log->target_type = User::class; $log->target_type = User::class;
@ -53,7 +53,15 @@ trait Loggable
} }
$item = call_user_func(array($log->target_type, 'find'), $log->target_id); $item = call_user_func(array($log->target_type, 'find'), $log->target_id);
$log->location_id = $item->location_id; $class = get_class($item);
if($class == Location::class) {
// We can checkout to a location
$log->location_id = $item->id;
} else if ($class== Asset::class) {
$log->location_id = $item->rtd_location_id;
} else {
$log->location_id = $item->location_id;
}
$log->note = $note; $log->note = $note;
$log->logaction('checkout'); $log->logaction('checkout');

View file

@ -127,9 +127,10 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
/** /**
* Get assets assigned to this user * Get assets assigned to this user
*/ */
public function assets() public function assignedAssets()
{ {
return $this->hasMany('\App\Models\Asset', 'assigned_to')->withTrashed(); return $this->morphMany('App\Models\Asset', 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
// return $this->hasMany('\App\Models\Asset', 'assigned_to')->withTrashed();
} }
/** /**

View file

@ -80,14 +80,14 @@ class AssetPresenter extends Presenter
$results['status_label'] = ''; $results['status_label'] = '';
$results['assigned_to'] = ''; $results['assigned_to'] = '';
if($assigned = $this->model->assigneduser) { if($assigned = $this->model->assignedTo) {
$results['status_label'] = 'Deployed'; $results['status_label'] = 'Deployed';
$results['assigned_to'] = (string) link_to_route('users.show', $assigned->present()->fullName(), $this->assigned_to ); $results['assigned_to'] = $assigned->present()->nameUrl();
} else if($this->model->assetstatus) { } else if($this->model->assetstatus) {
$results['status_label'] = $this->model->assetstatus->name; $results['status_label'] = $this->model->assetstatus->name;
} }
$results['location'] = ''; $results['location'] = '';
if (isset($assigned) and !empty($assignedLoc = $assigned->userloc)) { if (isset($assigned) and !empty($assignedLoc = $this->model->assetLoc)) {
$results['location'] = $assignedLoc->present()->nameUrl(); $results['location'] = $assignedLoc->present()->nameUrl();
} else if (!empty($this->model->defaultLoc)) { } else if (!empty($this->model->defaultLoc)) {
$results['location'] = $this->model->defaultLoc->present()->nameUrl(); $results['location'] = $this->model->defaultLoc->present()->nameUrl();

View file

@ -56,6 +56,15 @@ class LocationPresenter extends Presenter
return (string)link_to_route('locations.show', $this->name, $this->id); return (string)link_to_route('locations.show', $this->name, $this->id);
} }
/**
* Getter for Polymorphism.
* @return mixed
*/
public function name()
{
return $this->model->name;
}
/** /**
* Url to view this item. * Url to view this item.
* @return string * @return string

View file

@ -109,6 +109,15 @@ class UserPresenter extends Presenter
return "{$this->first_name} {$this->last_name}"; return "{$this->first_name} {$this->last_name}";
} }
/**
* Standard accessor.
* @TODO Remove presenter::fullName() entirely?
* @return string
*/
public function name()
{
return $this->fullName();
}
/** /**
* Returns the user Gravatar image url. * Returns the user Gravatar image url.
* *

View file

@ -47,14 +47,40 @@
<!-- User --> <!-- User -->
<div id="assigned_user" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}"> <div id="assigned_user" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
{{ Form::label('assigned_to', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }} {{ Form::label('assigned_user', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7 required"> <div class="col-md-7 required">
{{ Form::select('assigned_to', $users_list , Input::old('assigned_to', $asset->assigned_to), array('class'=>'select2', 'id'=>'assigned_to', 'style'=>'width:100%')) }} {{ Form::select('assigned_user', $users_list , Input::old('assigned_user', $asset->assigned_type == 'App\Models\User' ? $asset->assigned_to : 0), array('class'=>'select2', 'id'=>'assigned_user', 'style'=>'width:100%')) }}
{!! $errors->first('assigned_to', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!} {!! $errors->first('assigned_user', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div> </div>
<div class="col-md-1 col-sm-1 text-left"> <div class="col-md-1 col-sm-1 text-left">
<a href='#' data-toggle="modal" data-target="#createModal" data-dependency="user" data-select='assigned_to' class="btn btn-sm btn-default">New</a> <a href='#' data-toggle="modal" data-target="#createModal" data-dependency="user" data-select='assigned_user' class="btn btn-sm btn-default">New</a>
</div>
</div>
<!-- Assets -->
<div id="assigned_asset" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
{{ Form::label('assigned_asset', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7 required">
{{ Form::select('assigned_asset', $assets_list , Input::old('assigned_asset', $asset->assigned_type == 'App\Models\Asset' ? $asset->assigned_to : 0), array('class'=>'select2', 'id'=>'assigned_asset', 'style'=>'width:100%')) }}
{!! $errors->first('assigned_asset', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
<div class="col-md-1 col-sm-1 text-left">
<a href='#' data-toggle="modal" data-target="#createModal" data-dependency="user" data-select='assigned_asset' class="btn btn-sm btn-default">New</a>
</div>
</div>
<!-- Locations -->
<div id="assigned_location" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
{{ Form::label('assigned_location', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7 required">
{{ Form::select('assigned_location', $locations_list , Input::old('assigned_location', $asset->assigned_type == 'App\Models\Asset' ? $asset->assigned_to : 0), array('class'=>'select2', 'id'=>'assigned_location', 'style'=>'width:100%')) }}
{!! $errors->first('assigned_location', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
<div class="col-md-1 col-sm-1 text-left">
<a href='#' data-toggle="modal" data-target="#createModal" data-dependency="user" data-select='assigned_location' class="btn btn-sm btn-default">New</a>
</div> </div>
</div> </div>

View file

@ -229,7 +229,7 @@
@if ($asset->depreciation) @if ($asset->depreciation)
<tr> <tr>
<td>{{ trans('admin/hardware/form.depreciation') }}</td> <td>{{ trans('general.depreciation') }}</td>
<td> <td>
{{ $asset->depreciation->name }} {{ $asset->depreciation->name }}
({{ $asset->depreciation->months }} ({{ $asset->depreciation->months }}
@ -347,11 +347,13 @@
<img src="{{ url('/') }}/hardware/{{ $asset->id }}/qr_code" class="img-thumbnail pull-right" style="height: 100px; width: 100px; margin-right: 10px;"> <img src="{{ url('/') }}/hardware/{{ $asset->id }}/qr_code" class="img-thumbnail pull-right" style="height: 100px; width: 100px; margin-right: 10px;">
@endif @endif
@if (($asset->assigneduser) && ($asset->assigned_to > 0) && ($asset->deleted_at=='')) @if (($asset->assignedTo) && ($asset->assigned_to > 0) && ($asset->deleted_at==''))
<h4>{{ trans('admin/hardware/form.checkedout_to') }}</h4> <h4>{{ trans('admin/hardware/form.checkedout_to') }}</h4>
<p> <p>
<img src="{{ $asset->assigneduser->present()->gravatar() }}" class="user-image-inline" alt="{{ $asset->assigneduser->present()->fullName() }}"> @if($asset->assigned_type == User::class) <!-- Only users have avatars currently-->
<a href="{{ route('users.show', $asset->assigned_to) }}">{{ $asset->assigneduser->present()->fullName() }}</a> <img src="{{ $asset->assignedTo->present()->gravatar() }}" class="user-image-inline" alt="{{ $asset->assigneduser->present()->fullName() }}">
@endif
{!! $asset->assignedTo->present()->nameUrl() !!}
</p> </p>
<ul class="list-unstyled"> <ul class="list-unstyled">