Improvement: Better documentation, small refactors (#6017)

* Better documentation, small refactors

* Small comment fixes
This commit is contained in:
snipe 2018-08-01 00:06:41 -07:00 committed by GitHub
parent 6ae096a56f
commit 2c38036123
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 1661 additions and 427 deletions

View file

@ -76,10 +76,4 @@ class CreateAdmin extends Command
} }
// protected function getArguments()
// {
// return array(
// array('username', InputArgument::REQUIRED, 'Username'),
// );
// }
} }

View file

@ -49,6 +49,12 @@ class Kernel extends ConsoleKernel
$schedule->command('backup:clean')->daily(); $schedule->command('backup:clean')->daily();
} }
/**
* This method is required by Laravel to handle any console routes
* that are defined in routes/console.php
*
* @return void
*/
protected function commands() protected function commands()
{ {
require base_path('routes/console.php'); require base_path('routes/console.php');

View file

@ -114,15 +114,15 @@ class CategoriesController extends Controller
public function destroy($id) public function destroy($id)
{ {
$this->authorize('delete', Category::class); $this->authorize('delete', Category::class);
$category = Category::findOrFail($id); $category = Category::withCount('models as models_count', 'accessories as accessories_count','consumables as consumables_count','components as components_count')->findOrFail($id);
if ($category->has_models() > 0) { if ($category->models_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'model']))); return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'model'])));
} elseif ($category->accessories()->count() > 0) { } elseif ($category->accessories_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory']))); return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory'])));
} elseif ($category->consumables()->count() > 0) { } elseif ($category->consumables_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable']))); return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable'])));
} elseif ($category->components()->count() > 0) { } elseif ($category->components_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'component']))); return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'component'])));
} }
$category->delete(); $category->delete();

View file

@ -110,10 +110,10 @@ class DepreciationsController extends Controller
public function destroy($id) public function destroy($id)
{ {
$this->authorize('delete', Depreciation::class); $this->authorize('delete', Depreciation::class);
$depreciation = Depreciation::findOrFail($id); $depreciation = Depreciation::withCount('models as models_count')->findOrFail($id);
$this->authorize('delete', $depreciation); $this->authorize('delete', $depreciation);
if ($depreciation->has_models() > 0) { if ($depreciation->models_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', trans('admin/depreciations/message.assoc_users'))); return response()->json(Helper::formatStandardApiResponse('error', trans('admin/depreciations/message.assoc_users')));
} }

View file

@ -168,20 +168,21 @@ class CategoriesController extends Controller
{ {
$this->authorize('delete', Category::class); $this->authorize('delete', Category::class);
// Check if the category exists // Check if the category exists
if (is_null($category = Category::find($categoryId))) { if (is_null($category = Category::withCount('models as models_count', 'accessories as accessories_count','consumables as consumables_count','components as components_count')->findOrFail($categoryId))) {
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.not_found')); return redirect()->route('categories.index')->with('error', trans('admin/categories/message.not_found'));
} }
if ($category->has_models() > 0) { if ($category->models_count > 0) {
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'model'])); return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'model']));
} elseif ($category->accessories()->count() > 0) { } elseif ($category->accessories_count > 0) {
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory'])); return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory']));
} elseif ($category->consumables()->count() > 0) { } elseif ($category->consumables_count > 0) {
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable'])); return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable']));
} elseif ($category->components()->count() > 0) { } elseif ($category->components_count > 0) {
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'component'])); return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'component']));
} }
$category->delete(); $category->delete();
// Redirect to the locations management page // Redirect to the locations management page
return redirect()->route('categories.index')->with('success', trans('admin/categories/message.delete.success')); return redirect()->route('categories.index')->with('success', trans('admin/categories/message.delete.success'));

View file

@ -150,13 +150,13 @@ class DepreciationsController extends Controller
public function destroy($depreciationId) public function destroy($depreciationId)
{ {
// Check if the depreciation exists // Check if the depreciation exists
if (is_null($depreciation = Depreciation::find($depreciationId))) { if (is_null($depreciation = Depreciation::withCount('models as models_count')->find($depreciationId))) {
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.not_found')); return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.not_found'));
} }
$this->authorize('delete', $depreciation); $this->authorize('delete', $depreciation);
if ($depreciation->has_models() > 0) { if ($depreciation->models_count > 0) {
// Redirect to the asset management page // Redirect to the asset management page
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.assoc_users')); return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.assoc_users'));
} }

View file

@ -152,14 +152,11 @@ class ManufacturersController extends Controller
public function destroy($manufacturerId) public function destroy($manufacturerId)
{ {
$this->authorize('delete', Manufacturer::class); $this->authorize('delete', Manufacturer::class);
// Check if the manufacturer exists if (is_null($manufacturer = Manufacturer::withCount('models as models_count')->find($manufacturerId))) {
if (is_null($manufacturer = Manufacturer::find($manufacturerId))) {
// Redirect to the manufacturers page
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.not_found')); return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.not_found'));
} }
if ($manufacturer->has_models() > 0) { if ($manufacturer->models_count > 0) {
// Redirect to the asset management page
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.assoc_users')); return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.assoc_users'));
} }
@ -167,7 +164,7 @@ class ManufacturersController extends Controller
try { try {
unlink(public_path().'/uploads/manufacturers/'.$manufacturer->image); unlink(public_path().'/uploads/manufacturers/'.$manufacturer->image);
} catch (\Exception $e) { } catch (\Exception $e) {
\Log::error($e);
} }
} }

View file

@ -113,6 +113,13 @@ abstract class Importer
// Cached Values for import lookups // Cached Values for import lookups
protected $customFields; protected $customFields;
/**
* Sets up the database transaction and logging for the importer
*
* @return void
* @author Daniel Meltzer
* @since 5.0
*/
public function import() public function import()
{ {
$headerRow = $this->csv->fetchOne(); $headerRow = $this->csv->fetchOne();

View file

@ -101,13 +101,26 @@ class Accessory extends SnipeModel
/**
* Establishes the accessory -> supplier relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function supplier() public function supplier()
{ {
return $this->belongsTo('\App\Models\Supplier', 'supplier_id'); return $this->belongsTo('\App\Models\Supplier', 'supplier_id');
} }
/**
* Sets the requestable attribute on the accessory
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return void
*/
public function setRequestableAttribute($value) public function setRequestableAttribute($value)
{ {
if ($value == '') { if ($value == '') {
@ -117,24 +130,49 @@ class Accessory extends SnipeModel
return; return;
} }
/**
* Establishes the accessory -> company relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company() public function company()
{ {
return $this->belongsTo('\App\Models\Company', 'company_id'); return $this->belongsTo('\App\Models\Company', 'company_id');
} }
/**
* Establishes the accessory -> location relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location() public function location()
{ {
return $this->belongsTo('\App\Models\Location', 'location_id'); return $this->belongsTo('\App\Models\Location', 'location_id');
} }
/**
* Establishes the accessory -> category relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function category() public function category()
{ {
return $this->belongsTo('\App\Models\Category', 'category_id')->where('category_type', '=', 'accessory'); return $this->belongsTo('\App\Models\Category', 'category_id')->where('category_type', '=', 'accessory');
} }
/** /**
* Get action logs for this accessory * Returns the action logs associated with the accessory
*/ *
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetlog() public function assetlog()
{ {
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Accessory::class)->orderBy('created_at', 'desc')->withTrashed(); return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Accessory::class)->orderBy('created_at', 'desc')->withTrashed();
@ -173,6 +211,16 @@ class Accessory extends SnipeModel
} }
/**
* Sets the full image url
*
* @todo this should probably be moved out of the model and into a
* presenter or service provider
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return string
*/
public function getImageUrl() { public function getImageUrl() {
if ($this->image) { if ($this->image) {
return url('/').'/uploads/accessories/'.$this->image; return url('/').'/uploads/accessories/'.$this->image;
@ -181,31 +229,77 @@ class Accessory extends SnipeModel
} }
/**
* Establishes the accessory -> users relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function users() public function users()
{ {
return $this->belongsToMany('\App\Models\User', 'accessories_users', 'accessory_id', 'assigned_to')->withPivot('id')->withTrashed(); return $this->belongsToMany('\App\Models\User', 'accessories_users', 'accessory_id', 'assigned_to')->withPivot('id')->withTrashed();
} }
/**
* Checks whether or not the accessory has users
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return int
*/
public function hasUsers() public function hasUsers()
{ {
return $this->belongsToMany('\App\Models\User', 'accessories_users', 'accessory_id', 'assigned_to')->count(); return $this->belongsToMany('\App\Models\User', 'accessories_users', 'accessory_id', 'assigned_to')->count();
} }
/**
* Establishes the accessory -> manufacturer relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manufacturer() public function manufacturer()
{ {
return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id'); return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id');
} }
/**
* Determins whether or not an email should be sent for checkin/checkout of this
* accessory based on the category it belongs to.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return boolean
*/
public function checkin_email() public function checkin_email()
{ {
return $this->category->checkin_email; return $this->category->checkin_email;
} }
/**
* Determines whether or not the accessory should require the user to
* accept it via email.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return boolean
*/
public function requireAcceptance() public function requireAcceptance()
{ {
return $this->category->require_acceptance; return $this->category->require_acceptance;
} }
/**
* Checks for a category-specific EULA, and if that doesn't exist,
* checks for a settings level EULA
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return string
*/
public function getEula() public function getEula()
{ {
@ -219,6 +313,13 @@ class Accessory extends SnipeModel
return null; return null;
} }
/**
* Check how many items of an accessory remain
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return int
*/
public function numRemaining() public function numRemaining()
{ {
$checkedout = $this->users->count(); $checkedout = $this->users->count();

View file

@ -41,9 +41,15 @@ class Actionlog extends SnipeModel
*/ */
protected $searchableRelations = [ protected $searchableRelations = [
'company' => ['name'] 'company' => ['name']
]; ];
// Overridden from Builder to automatically add the company /**
* Override from Builder to automatically add the company
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public static function boot() public static function boot()
{ {
parent::boot(); parent::boot();
@ -60,17 +66,39 @@ class Actionlog extends SnipeModel
} }
}); });
} }
// Eloquent Relationships below
/**
* Establishes the actionlog -> item relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function item() public function item()
{ {
return $this->morphTo('item')->withTrashed(); return $this->morphTo('item')->withTrashed();
} }
/**
* Establishes the actionlog -> company relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company() public function company()
{ {
return $this->hasMany('\App\Models\Company', 'id', 'company_id'); return $this->hasMany('\App\Models\Company', 'id', 'company_id');
} }
/**
* Establishes the actionlog -> item type relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function itemType() public function itemType()
{ {
@ -80,6 +108,13 @@ class Actionlog extends SnipeModel
return camel_case(class_basename($this->item_type)); return camel_case(class_basename($this->item_type));
} }
/**
* Establishes the actionlog -> target type relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function targetType() public function targetType()
{ {
if ($this->target_type == User::class) { if ($this->target_type == User::class) {
@ -88,28 +123,14 @@ class Actionlog extends SnipeModel
return camel_case(class_basename($this->target_type)); return camel_case(class_basename($this->target_type));
} }
public function parseItemRoute()
{
if ($this->itemType() == "asset") {
$itemroute = 'assets';
} elseif ($this->itemType() == "accessory") {
$itemroute = 'accessories';
} elseif ($this->itemType()=="consumable") {
$itemroute = 'consumables';
} elseif ($this->itemType()=="license") {
$itemroute = 'licenses';
} elseif ($this->itemType()=="component") {
$itemroute = 'components';
} else {
$itemroute = '';
}
return $itemroute;
}
/**
* Establishes the actionlog -> uploads relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function uploads() public function uploads()
{ {
return $this->morphTo('item') return $this->morphTo('item')
@ -117,39 +138,62 @@ class Actionlog extends SnipeModel
->withTrashed(); ->withTrashed();
} }
/**
* Establishes the actionlog -> userlog relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function userlog() public function userlog()
{ {
return $this->target(); return $this->target();
} }
/**
* Establishes the actionlog -> user relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function user() public function user()
{ {
return $this->belongsTo(User::class, 'user_id') return $this->belongsTo(User::class, 'user_id')
->withTrashed(); ->withTrashed();
} }
/**
* Establishes the actionlog -> target relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function target() public function target()
{ {
return $this->morphTo('target')->withTrashed(); return $this->morphTo('target')->withTrashed();
} }
public function childlogs() /**
{ * Establishes the actionlog -> location relationship
return $this->hasMany('\App\Models\ActionLog', 'thread_id'); *
} * @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
public function parentlog() * @return \Illuminate\Database\Eloquent\Relations\Relation
{ */
return $this->belongsTo('\App\Models\ActionLog', 'thread_id');
}
public function location() { public function location() {
return $this->belongsTo('\App\Models\Location', 'location_id' )->withTrashed(); return $this->belongsTo('\App\Models\Location', 'location_id' )->withTrashed();
} }
/** /**
* Check if the file exists, and if it does, force a download * Check if the file exists, and if it does, force a download
**/ *
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return string | false
*/
public function get_src($type = 'assets', $fieldname = 'filename') public function get_src($type = 'assets', $fieldname = 'filename')
{ {
if ($this->filename!='') { if ($this->filename!='') {
@ -162,8 +206,12 @@ class Actionlog extends SnipeModel
/** /**
* Get the parent category name * Saves the log record with the action type
*/ *
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return boolean
*/
public function logaction($actiontype) public function logaction($actiontype)
{ {
@ -176,6 +224,13 @@ class Actionlog extends SnipeModel
} }
} }
/**
* Calculate the number of days until the next audit
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return int
*/
public function daysUntilNextAudit($monthInterval = 12, $asset = null) { public function daysUntilNextAudit($monthInterval = 12, $asset = null) {
$now = Carbon::now(); $now = Carbon::now();
@ -192,6 +247,13 @@ class Actionlog extends SnipeModel
return $next_audit_days; return $next_audit_days;
} }
/**
* Calculate the date of the next audit
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Datetime
*/
public function calcNextAuditDate($monthInterval = 12, $asset = null) { public function calcNextAuditDate($monthInterval = 12, $asset = null) {
$last_audit_date = Carbon::parse($this->created_at); $last_audit_date = Carbon::parse($this->created_at);
@ -204,12 +266,12 @@ class Actionlog extends SnipeModel
} }
/** /**
* getListingOfActionLogsChronologicalOrder * Gets action logs in chronological order, excluding uploads
* *
* @return mixed * @author Vincent Sposato <vincent.sposato@gmail.com>
* @author Vincent Sposato <vincent.sposato@gmail.com> * @since v1.0
* @version v1.0 * @return \Illuminate\Database\Eloquent\Collection
*/ */
public function getListingOfActionLogsChronologicalOrder() public function getListingOfActionLogsChronologicalOrder()
{ {

View file

@ -174,12 +174,26 @@ class Asset extends Depreciable
return null; return null;
} }
/**
* Establishes the asset -> company relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company() public function company()
{ {
return $this->belongsTo('\App\Models\Company', 'company_id'); return $this->belongsTo('\App\Models\Company', 'company_id');
} }
/**
* Determines if an asset is available for checkout
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return boolean
*/
public function availableForCheckout() public function availableForCheckout()
{ {
if ( if (
@ -192,8 +206,13 @@ class Asset extends Depreciable
return false; return false;
} }
/** /**
* Checkout asset * Checks the asset out to the target
*
* @todo The admin parameter is never used. Can probably be removed.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param User $user * @param User $user
* @param User $admin * @param User $admin
* @param Carbon $checkout_at * @param Carbon $checkout_at
@ -201,8 +220,9 @@ class Asset extends Depreciable
* @param string $note * @param string $note
* @param null $name * @param null $name
* @return bool * @return bool
* @since [v3.0]
* @return boolean
*/ */
//FIXME: The admin parameter is never used. Can probably be removed.
public function checkOut($target, $admin = null, $checkout_at = null, $expected_checkin = null, $note = null, $name = null, $location = null) public function checkOut($target, $admin = null, $checkout_at = null, $expected_checkin = null, $note = null, $name = null, $location = null)
{ {
if (!$target) { if (!$target) {
@ -253,6 +273,13 @@ class Asset extends Depreciable
return false; return false;
} }
/**
* Sets the detailedNameAttribute
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return string
*/
public function getDetailedNameAttribute() public function getDetailedNameAttribute()
{ {
if ($this->assignedto) { if ($this->assignedto) {
@ -263,31 +290,54 @@ class Asset extends Depreciable
return $this->asset_tag . ' - ' . $this->name . ' (' . $user_name . ') ' . ($this->model) ? $this->model->name: ''; return $this->asset_tag . ' - ' . $this->name . ' (' . $user_name . ') ' . ($this->model) ? $this->model->name: '';
} }
public function validationRules($id = '0') /**
* Pulls in the validation rules
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return array
*/
public function validationRules()
{ {
return $this->rules; return $this->rules;
} }
/** /**
* Set depreciation relationship * Establishes the asset -> depreciation relationship
*/ *
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function depreciation() public function depreciation()
{ {
return $this->model->belongsTo('\App\Models\Depreciation', 'depreciation_id'); return $this->model->belongsTo('\App\Models\Depreciation', 'depreciation_id');
} }
/** /**
* Get components assigned to this asset * Get components assigned to this asset
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function components() public function components()
{ {
return $this->belongsToMany('\App\Models\Component', 'components_assets', 'asset_id', 'component_id')->withPivot('id', 'assigned_qty')->withTrashed(); return $this->belongsToMany('\App\Models\Component', 'components_assets', 'asset_id', 'component_id')->withPivot('id', 'assigned_qty')->withTrashed();
} }
/**
* Get depreciation attribute from associated asset model /**
*/ * Get depreciation attribute from associated asset model
*
* @todo Is this still needed?
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function get_depreciation() public function get_depreciation()
{ {
if (($this->model) && ($this->model->depreciation)) { if (($this->model) && ($this->model->depreciation)) {
@ -295,9 +345,14 @@ class Asset extends Depreciable
} }
} }
/**
* Get uploads for this asset /**
*/ * Get uploads for this asset
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function uploads() public function uploads()
{ {
return $this->hasMany('\App\Models\Actionlog', 'item_id') return $this->hasMany('\App\Models\Actionlog', 'item_id')
@ -307,29 +362,58 @@ class Asset extends Depreciable
->orderBy('created_at', 'desc'); ->orderBy('created_at', 'desc');
} }
/** /**
* Determines whether the asset is checked out to a user
*
* Even though we allow allow for checkout to things beyond users * Even though we allow allow for checkout to things beyond users
* this method is an easy way of seeing if we are checked out to a user. * this method is an easy way of seeing if we are checked out to a user.
* @return mixed *
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return boolean
*/ */
public function checkedOutToUser() public function checkedOutToUser()
{ {
return $this->assignedType() === self::USER; return $this->assignedType() === self::USER;
} }
/**
* Get the target this asset is checked out to
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assignedTo() public function assignedTo()
{ {
return $this->morphTo('assigned', 'assigned_type', 'assigned_to'); return $this->morphTo('assigned', 'assigned_type', 'assigned_to');
} }
/**
* Gets assets assigned to this asset
*
* Sigh.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assignedAssets() public function assignedAssets()
{ {
return $this->morphMany('App\Models\Asset', 'assigned', 'assigned_type', 'assigned_to')->withTrashed(); 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
*
* @todo Refactor this if possible. It's awful.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \ArrayObject
*/
public function assetLoc($iterations = 1,$first_asset = null) public function assetLoc($iterations = 1,$first_asset = null)
{ {
if (!empty($this->assignedType())) { if (!empty($this->assignedType())) {
@ -364,19 +448,40 @@ class Asset extends Depreciable
return $this->defaultLoc; return $this->defaultLoc;
} }
/**
* Gets the lowercased name of the type of target the asset is assigned to
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return string
*/
public function assignedType() public function assignedType()
{ {
return strtolower(class_basename($this->assigned_type)); 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
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function defaultLoc() public function defaultLoc()
{ {
return $this->belongsTo('\App\Models\Location', 'rtd_location_id'); return $this->belongsTo('\App\Models\Location', 'rtd_location_id');
} }
/**
* Get the image URL of the asset.
*
* Check first to see if there is a specific image uploaded to the asset,
* and if not, check for an image uploaded to the asset model.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return string | false
*/
public function getImageUrl() public function getImageUrl()
{ {
if ($this->image && !empty($this->image)) { if ($this->image && !empty($this->image)) {
@ -388,9 +493,13 @@ class Asset extends Depreciable
} }
/** /**
* Get action logs for this asset * Get the asset's logs
*/ *
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetlog() public function assetlog()
{ {
return $this->hasMany('\App\Models\Actionlog', 'item_id') return $this->hasMany('\App\Models\Actionlog', 'item_id')
@ -400,7 +509,11 @@ class Asset extends Depreciable
} }
/** /**
* Get checkouts * Get the list of checkouts for this asset
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function checkouts() public function checkouts()
{ {
@ -410,7 +523,11 @@ class Asset extends Depreciable
} }
/** /**
* Get checkins * Get the list of checkins for this asset
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function checkins() public function checkins()
{ {
@ -421,7 +538,11 @@ class Asset extends Depreciable
} }
/** /**
* Get user requests * Get the asset's user requests
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function userRequests() public function userRequests()
{ {
@ -432,71 +553,65 @@ class Asset extends Depreciable
} }
/** /**
* assetmaintenances * Get maintenances for this asset
* Get improvements for this asset *
* * @author Vincent Sposato <vincent.sposato@gmail.com>
* @return mixed * @since 1.0
* @author Vincent Sposato <vincent.sposato@gmail.com> * @return \Illuminate\Database\Eloquent\Relations\Relation
* @version v1.0 */
*/
public function assetmaintenances() public function assetmaintenances()
{ {
return $this->hasMany('\App\Models\AssetMaintenance', 'asset_id') return $this->hasMany('\App\Models\AssetMaintenance', 'asset_id')
->orderBy('created_at', 'desc'); ->orderBy('created_at', 'desc');
} }
/** /**
* Get action logs for this asset * Get action logs history for this asset
*/ *
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser() public function adminuser()
{ {
return $this->belongsTo('\App\Models\User', 'user_id'); return $this->belongsTo('\App\Models\User', 'user_id');
} }
/**
* Get total assets
*/
public static function assetcount()
{
return Company::scopeCompanyables(Asset::where('physical', '=', '1'))
->whereNull('deleted_at', 'and')
->count();
}
/**
* Get total assets not checked out
*/
public static function availassetcount()
{
return Asset::RTD()
->whereNull('deleted_at')
->count();
}
/** /**
* Get requestable assets * Establishes the asset -> status relationship
*/ *
public static function getRequestable() * @author [A. Gianotto] [<snipe@snipe.net>]
{ * @since [v1.0]
return Asset::Requestable() * @return \Illuminate\Database\Eloquent\Relations\Relation
->whereNull('deleted_at') */
->count();
}
/**
* Get asset status
*/
public function assetstatus() public function assetstatus()
{ {
return $this->belongsTo('\App\Models\Statuslabel', 'status_id'); return $this->belongsTo('\App\Models\Statuslabel', 'status_id');
} }
/**
* Establishes the asset -> model relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function model() public function model()
{ {
return $this->belongsTo('\App\Models\AssetModel', 'model_id')->withTrashed(); return $this->belongsTo('\App\Models\AssetModel', 'model_id')->withTrashed();
} }
/**
* Return the assets with a warranty expiring within x days
*
* @param $days
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return mixed
*/
public static function getExpiringWarrantee($days = 30) public static function getExpiringWarrantee($days = 30)
{ {
return Asset::where('archived', '=', '0') return Asset::where('archived', '=', '0')
@ -510,25 +625,50 @@ class Asset extends Depreciable
->get(); ->get();
} }
/**
* Get the license seat information /**
**/ * Establishes the asset -> assigned licenses relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function licenses() public function licenses()
{ {
return $this->belongsToMany('\App\Models\License', 'license_seats', 'asset_id', 'license_id'); return $this->belongsToMany('\App\Models\License', 'license_seats', 'asset_id', 'license_id');
} }
/**
* Establishes the asset -> status relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function licenseseats() public function licenseseats()
{ {
return $this->hasMany('\App\Models\LicenseSeat', 'asset_id'); return $this->hasMany('\App\Models\LicenseSeat', 'asset_id');
} }
/**
* Establishes the asset -> aupplier relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function supplier() public function supplier()
{ {
return $this->belongsTo('\App\Models\Supplier', 'supplier_id'); return $this->belongsTo('\App\Models\Supplier', 'supplier_id');
} }
/**
* Establishes the asset -> location relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location() public function location()
{ {
return $this->belongsTo('\App\Models\Location', 'location_id'); return $this->belongsTo('\App\Models\Location', 'location_id');
@ -536,9 +676,13 @@ class Asset extends Depreciable
/** /**
* Get auto-increment * Get the next autoincremented asset tag
*/ *
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return string | false
*/
public static function autoincrement_asset() public static function autoincrement_asset()
{ {
$settings = \App\Models\Setting::getSettings(); $settings = \App\Models\Setting::getSettings();
@ -561,10 +705,15 @@ class Asset extends Depreciable
} }
} }
/*
* Get the next base number for the auto-incrementer. We'll add the zerofill and /**
* prefixes on the fly as we generate the number * Get the next base number for the auto-incrementer.
* *
* We'll add the zerofill and prefixes on the fly as we generate the number.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return int
*/ */
public static function nextAutoIncrement($assets) public static function nextAutoIncrement($assets)
{ {
@ -590,23 +739,53 @@ class Asset extends Depreciable
/**
* Add zerofilling based on Settings
*
* We'll add the zerofill and prefixes on the fly as we generate the number.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return string
*/
public static function zerofill($num, $zerofill = 3) public static function zerofill($num, $zerofill = 3)
{ {
return str_pad($num, $zerofill, '0', STR_PAD_LEFT); return str_pad($num, $zerofill, '0', STR_PAD_LEFT);
} }
/**
* Determine whether to send a checkin/checkout email based on
* asset model category
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return boolean
*/
public function checkin_email() public function checkin_email()
{ {
return $this->model->category->checkin_email; return $this->model->category->checkin_email;
} }
/**
* Determine whether this asset requires acceptance by the assigned user
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return boolean
*/
public function requireAcceptance() public function requireAcceptance()
{ {
return $this->model->category->require_acceptance; return $this->model->category->require_acceptance;
} }
/**
* Checks for a category-specific EULA, and if that doesn't exist,
* checks for a settings level EULA
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return string | false
*/
public function getEula() public function getEula()
{ {
$Parsedown = new \Parsedown(); $Parsedown = new \Parsedown();
@ -620,91 +799,92 @@ class Asset extends Depreciable
} }
} }
/**
* -----------------------------------------------
* BEGIN QUERY SCOPES
* -----------------------------------------------
**/
/** /**
* Run additional, advanced searches. * Run additional, advanced searches.
* *
* @param Illuminate\Database\Eloquent\Builder $query * @param \Illuminate\Database\Eloquent\Builder $query
* @param array $terms The search terms * @param array $terms The search terms
* @return Illuminate\Database\Eloquent\Builder * @return \Illuminate\Database\Eloquent\Builder
*/ */
public function advancedTextSearch(Builder $query, array $terms) { public function advancedTextSearch(Builder $query, array $terms) {
/**
/** * Assigned user
* Assigned user */
*/ $query = $query->leftJoin('users as assets_users',function ($leftJoin) {
$query = $query->leftJoin('users as assets_users',function ($leftJoin) {
$leftJoin->on("assets_users.id", "=", "assets.assigned_to") $leftJoin->on("assets_users.id", "=", "assets.assigned_to")
->where("assets.assigned_type", "=", User::class); ->where("assets.assigned_type", "=", User::class);
}); });
foreach($terms as $term) { foreach($terms as $term) {
$query = $query $query = $query
->orWhere('assets_users.first_name', 'LIKE', '%'.$term.'%') ->orWhere('assets_users.first_name', 'LIKE', '%'.$term.'%')
->orWhere('assets_users.last_name', 'LIKE', '%'.$term.'%') ->orWhere('assets_users.last_name', 'LIKE', '%'.$term.'%')
->orWhere('assets_users.username', 'LIKE', '%'.$term.'%') ->orWhere('assets_users.username', 'LIKE', '%'.$term.'%')
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$term%", "%$term%"]); ->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$term%", "%$term%"]);
} }
/** /**
* Assigned location * Assigned location
*/ */
$query = $query->leftJoin('locations as assets_locations',function ($leftJoin) { $query = $query->leftJoin('locations as assets_locations',function ($leftJoin) {
$leftJoin->on("assets_locations.id","=","assets.assigned_to") $leftJoin->on("assets_locations.id","=","assets.assigned_to")
->where("assets.assigned_type","=",Location::class); ->where("assets.assigned_type","=",Location::class);
}); });
foreach($terms as $term) { foreach($terms as $term) {
$query = $query->orWhere('assets_locations.name', 'LIKE', '%'.$term.'%'); $query = $query->orWhere('assets_locations.name', 'LIKE', '%'.$term.'%');
} }
/** /**
* Assigned assets * Assigned assets
*/ */
$query = $query->leftJoin('assets as assigned_assets',function ($leftJoin) { $query = $query->leftJoin('assets as assigned_assets',function ($leftJoin) {
$leftJoin->on('assigned_assets.id', '=', 'assets.assigned_to') $leftJoin->on('assigned_assets.id', '=', 'assets.assigned_to')
->where('assets.assigned_type', '=', Asset::class); ->where('assets.assigned_type', '=', Asset::class);
}); });
foreach($terms as $term) { foreach($terms as $term) {
$query = $query->orWhere('assigned_assets.name', 'LIKE', '%'.$term.'%'); $query = $query->orWhere('assigned_assets.name', 'LIKE', '%'.$term.'%');
}
return $query; }
return $query;
} }
/**
* -----------------------------------------------
* BEGIN QUERY SCOPES
* -----------------------------------------------
**/
/** /**
* Query builder scope for hardware * Query builder scope for hardware
* *
* @param \Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* *
* @return \Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeHardware($query) public function scopeHardware($query)
{ {
return $query->where('physical', '=', '1'); return $query->where('physical', '=', '1');
} }
/** /**
* Query builder scope for pending assets * Query builder scope for pending assets
* *
* @param \Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* *
* @return \Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopePending($query) public function scopePending($query)
{ {

View file

@ -22,7 +22,6 @@ class AssetMaintenance extends Model implements ICompanyableChild
protected $dates = [ 'deleted_at', 'start_date' , 'completion_date']; protected $dates = [ 'deleted_at', 'start_date' , 'completion_date'];
protected $table = 'asset_maintenances'; protected $table = 'asset_maintenances';
// Declaring rules for form validation
protected $rules = [ protected $rules = [
'asset_id' => 'required|integer', 'asset_id' => 'required|integer',
'supplier_id' => 'required|integer', 'supplier_id' => 'required|integer',

View file

@ -87,44 +87,92 @@ class AssetModel extends SnipeModel
'depreciation' => ['name'], 'depreciation' => ['name'],
'category' => ['name'], 'category' => ['name'],
'manufacturer' => ['name'], 'manufacturer' => ['name'],
]; ];
/**
* Establishes the model -> assets relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets() public function assets()
{ {
return $this->hasMany('\App\Models\Asset', 'model_id'); return $this->hasMany('\App\Models\Asset', 'model_id');
} }
/**
* Establishes the model -> category relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function category() public function category()
{ {
return $this->belongsTo('\App\Models\Category', 'category_id'); return $this->belongsTo('\App\Models\Category', 'category_id');
} }
/**
* Establishes the model -> depreciation relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function depreciation() public function depreciation()
{ {
return $this->belongsTo('\App\Models\Depreciation', 'depreciation_id'); return $this->belongsTo('\App\Models\Depreciation', 'depreciation_id');
} }
public function adminuser()
{
return $this->belongsTo('\App\Models\User', 'user_id');
}
/**
* Establishes the model -> manufacturer relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manufacturer() public function manufacturer()
{ {
return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id'); return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id');
} }
/**
* Establishes the model -> fieldset relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function fieldset() public function fieldset()
{ {
return $this->belongsTo('\App\Models\CustomFieldset', 'fieldset_id'); return $this->belongsTo('\App\Models\CustomFieldset', 'fieldset_id');
} }
/**
* Establishes the model -> custom field default values relationship
*
* @author hannah tinkler
* @since [v4.3]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function defaultValues() public function defaultValues()
{ {
return $this->belongsToMany('\App\Models\CustomField', 'models_custom_fields')->withPivot('default_value'); return $this->belongsToMany('\App\Models\CustomField', 'models_custom_fields')->withPivot('default_value');
} }
/**
* Gets the full url for the image
*
* @todo this should probably be moved
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function getImageUrl() { public function getImageUrl() {
if ($this->image) { if ($this->image) {
return url('/').'/uploads/models/'.$this->image; return url('/').'/uploads/models/'.$this->image;
@ -141,8 +189,8 @@ class AssetModel extends SnipeModel
/** /**
* Query builder scope for Deleted assets * Query builder scope for Deleted assets
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeDeleted($query) public function scopeDeleted($query)

View file

@ -80,31 +80,62 @@ class Category extends SnipeModel
*/ */
protected $searchableRelations = []; protected $searchableRelations = [];
public function has_models()
{
return $this->hasMany('\App\Models\AssetModel', 'category_id')->count();
}
/**
* Establishes the category -> accessories relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function accessories() public function accessories()
{ {
return $this->hasMany('\App\Models\Accessory'); return $this->hasMany('\App\Models\Accessory');
} }
/**
* Establishes the category -> licenses relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.3]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function licenses() public function licenses()
{ {
return $this->hasMany('\App\Models\License'); return $this->hasMany('\App\Models\License');
} }
/**
* Establishes the category -> consumables relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function consumables() public function consumables()
{ {
return $this->hasMany('\App\Models\Consumable'); return $this->hasMany('\App\Models\Consumable');
} }
/**
* Establishes the category -> consumables relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function components() public function components()
{ {
return $this->hasMany('\App\Models\Component'); return $this->hasMany('\App\Models\Component');
} }
/**
* Get the number of items in the category
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return int
*/
public function itemCount() public function itemCount()
{ {
switch ($this->category_type) { switch ($this->category_type) {
@ -120,16 +151,38 @@ class Category extends SnipeModel
return '0'; return '0';
} }
/**
* Establishes the category -> assets relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets() public function assets()
{ {
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'category_id', 'model_id'); return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'category_id', 'model_id');
} }
/**
* Establishes the category -> models relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function models() public function models()
{ {
return $this->hasMany('\App\Models\AssetModel', 'category_id'); return $this->hasMany('\App\Models\AssetModel', 'category_id');
} }
/**
* Checks for a category-specific EULA, and if that doesn't exist,
* checks for a settings level EULA
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return string | null
*/
public function getEula() public function getEula()
{ {
@ -145,15 +198,22 @@ class Category extends SnipeModel
} }
/** /**
* scopeRequiresAcceptance * -----------------------------------------------
* BEGIN QUERY SCOPES
* -----------------------------------------------
**/
/**
* Query builder scope for whether or not the category requires acceptance
* *
* @param $query
*
* @return mixed
* @author Vincent Sposato <vincent.sposato@gmail.com> * @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0 *
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeRequiresAcceptance($query) public function scopeRequiresAcceptance($query)
{ {

View file

@ -86,43 +86,89 @@ class Component extends SnipeModel
'category' => ['name'], 'category' => ['name'],
'company' => ['name'], 'company' => ['name'],
'location' => ['name'], 'location' => ['name'],
]; ];
/**
* Establishes the component -> location relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location() public function location()
{ {
return $this->belongsTo('\App\Models\Location', 'location_id'); return $this->belongsTo('\App\Models\Location', 'location_id');
} }
/**
* Establishes the component -> assets relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets() public function assets()
{ {
return $this->belongsToMany('\App\Models\Asset', 'components_assets')->withPivot('id', 'assigned_qty', 'created_at', 'user_id'); return $this->belongsToMany('\App\Models\Asset', 'components_assets')->withPivot('id', 'assigned_qty', 'created_at', 'user_id');
} }
/**
* Establishes the component -> admin user relationship
*
* @todo this is probably not needed - refactor
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function admin() public function admin()
{ {
return $this->belongsTo('\App\Models\User', 'user_id'); return $this->belongsTo('\App\Models\User', 'user_id');
} }
/**
* Establishes the component -> company relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company() public function company()
{ {
return $this->belongsTo('\App\Models\Company', 'company_id'); return $this->belongsTo('\App\Models\Company', 'company_id');
} }
/**
* Establishes the component -> category relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function category() public function category()
{ {
return $this->belongsTo('\App\Models\Category', 'category_id'); return $this->belongsTo('\App\Models\Category', 'category_id');
} }
/** /**
* Get action logs for this consumable * Establishes the component -> action logs relationship
*/ *
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetlog() public function assetlog()
{ {
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Component::class)->orderBy('created_at', 'desc')->withTrashed(); return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Component::class)->orderBy('created_at', 'desc')->withTrashed();
} }
/**
* Check how many items within a component are remaining
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return int
*/
public function numRemaining() public function numRemaining()
{ {
$checkedout = 0; $checkedout = 0;
@ -140,10 +186,10 @@ class Component extends SnipeModel
/** /**
* Query builder scope to order on company * Query builder scope to order on company
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderCategory($query, $order) public function scopeOrderCategory($query, $order)
{ {
@ -153,10 +199,10 @@ class Component extends SnipeModel
/** /**
* Query builder scope to order on company * Query builder scope to order on company
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderLocation($query, $order) public function scopeOrderLocation($query, $order)
{ {
@ -167,10 +213,10 @@ class Component extends SnipeModel
/** /**
* Query builder scope to order on company * Query builder scope to order on company
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderCompany($query, $order) public function scopeOrderCompany($query, $order)
{ {

View file

@ -88,8 +88,21 @@ class Consumable extends SnipeModel
'company' => ['name'], 'company' => ['name'],
'location' => ['name'], 'location' => ['name'],
'manufacturer' => ['name'], 'manufacturer' => ['name'],
]; ];
/**
* Sets the attribute of whether or not the consumable is requestable
*
* This isn't really implemented yet, as you can't currently request a consumable
* however it will be implemented in the future, and we needed to include
* this method here so all of our polymorphic methods don't break.
*
* @todo Update this comment once it's been implemented
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function setRequestableAttribute($value) public function setRequestableAttribute($value)
{ {
if ($value == '') { if ($value == '') {
@ -99,44 +112,98 @@ class Consumable extends SnipeModel
return; return;
} }
/**
* Establishes the consumable -> admin user relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function admin() public function admin()
{ {
return $this->belongsTo('\App\Models\User', 'user_id'); return $this->belongsTo('\App\Models\User', 'user_id');
} }
/**
* Establishes the component -> assignments relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function consumableAssignments() public function consumableAssignments()
{ {
return $this->hasMany('\App\Models\ConsumableAssignment'); return $this->hasMany('\App\Models\ConsumableAssignment');
} }
/**
* Establishes the component -> company relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company() public function company()
{ {
return $this->belongsTo('\App\Models\Company', 'company_id'); return $this->belongsTo('\App\Models\Company', 'company_id');
} }
/**
* Establishes the component -> manufacturer relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manufacturer() public function manufacturer()
{ {
return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id'); return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id');
} }
/**
* Establishes the component -> location relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location() public function location()
{ {
return $this->belongsTo('\App\Models\Location', 'location_id'); return $this->belongsTo('\App\Models\Location', 'location_id');
} }
/**
* Establishes the component -> category relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function category() public function category()
{ {
return $this->belongsTo('\App\Models\Category', 'category_id'); return $this->belongsTo('\App\Models\Category', 'category_id');
} }
/** /**
* Get action logs for this consumable * Establishes the component -> action logs relationship
*/ *
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetlog() public function assetlog()
{ {
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Consumable::class)->orderBy('created_at', 'desc')->withTrashed(); return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Consumable::class)->orderBy('created_at', 'desc')->withTrashed();
} }
/**
* Gets the full image url for the consumable
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return string | false
*/
public function getImageUrl() { public function getImageUrl() {
if ($this->image) { if ($this->image) {
return url('/').'/uploads/consumables/'.$this->image; return url('/').'/uploads/consumables/'.$this->image;
@ -145,27 +212,52 @@ class Consumable extends SnipeModel
} }
/**
* Establishes the component -> users relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function users() public function users()
{ {
return $this->belongsToMany('\App\Models\User', 'consumables_users', 'consumable_id', 'assigned_to')->withPivot('user_id')->withTrashed()->withTimestamps(); return $this->belongsToMany('\App\Models\User', 'consumables_users', 'consumable_id', 'assigned_to')->withPivot('user_id')->withTrashed()->withTimestamps();
} }
public function hasUsers()
{
return $this->belongsToMany('\App\Models\User', 'consumables_users', 'consumable_id', 'assigned_to')->count();
}
/**
* Determine whether to send a checkin/checkout email based on
* asset model category
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return boolean
*/
public function checkin_email() public function checkin_email()
{ {
return $this->category->checkin_email; return $this->category->checkin_email;
} }
/**
* Determine whether this asset requires acceptance by the assigned user
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return boolean
*/
public function requireAcceptance() public function requireAcceptance()
{ {
return $this->category->require_acceptance; return $this->category->require_acceptance;
} }
/**
* Checks for a category-specific EULA, and if that doesn't exist,
* checks for a settings level EULA
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return string | false
*/
public function getEula() public function getEula()
{ {
@ -181,6 +273,13 @@ class Consumable extends SnipeModel
} }
/**
* Checks the number of available consumables
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return int
*/
public function numRemaining() public function numRemaining()
{ {
$checkedout = $this->users->count(); $checkedout = $this->users->count();
@ -192,10 +291,10 @@ class Consumable extends SnipeModel
/** /**
* Query builder scope to order on company * Query builder scope to order on company
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderCategory($query, $order) public function scopeOrderCategory($query, $order)
{ {
@ -205,10 +304,10 @@ class Consumable extends SnipeModel
/** /**
* Query builder scope to order on location * Query builder scope to order on location
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param text $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderLocation($query, $order) public function scopeOrderLocation($query, $order)
{ {
@ -218,10 +317,10 @@ class Consumable extends SnipeModel
/** /**
* Query builder scope to order on manufacturer * Query builder scope to order on manufacturer
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderManufacturer($query, $order) public function scopeOrderManufacturer($query, $order)
{ {
@ -232,10 +331,10 @@ class Consumable extends SnipeModel
/** /**
* Query builder scope to order on company * Query builder scope to order on company
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderCompany($query, $order) public function scopeOrderCompany($query, $order)
{ {

View file

@ -46,10 +46,15 @@ class CustomField extends Model
'show_in_email', 'show_in_email',
]; ];
// This is confusing, since it's actually the custom fields table that /**
// we're usually modifying, but since we alter the assets table, we have to * This is confusing, since it's actually the custom fields table that
// say that here, otherwise the new fields get added onto the custom fields * we're usually modifying, but since we alter the assets table, we have to
// table instead of the assets table. * say that here, otherwise the new fields get added onto the custom fields
* table instead of the assets table.
*
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @since [v3.0]
*/
public static $table_name = "assets"; public static $table_name = "assets";
@ -138,16 +143,37 @@ class CustomField extends Model
}); });
} }
/**
* Establishes the customfield -> fieldset relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function fieldset() public function fieldset()
{ {
return $this->belongsToMany('\App\Models\CustomFieldset'); return $this->belongsToMany('\App\Models\CustomFieldset');
} }
/**
* Establishes the customfield -> admin user relationship
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function user() public function user()
{ {
return $this->belongsTo('\App\Models\User'); return $this->belongsTo('\App\Models\User');
} }
/**
* Establishes the customfield -> default values relationship
*
* @author Hannah Tinkler
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function defaultValues() public function defaultValues()
{ {
return $this->belongsToMany('\App\Models\AssetModel', 'models_custom_fields')->withPivot('default_value'); return $this->belongsToMany('\App\Models\AssetModel', 'models_custom_fields')->withPivot('default_value');
@ -169,11 +195,28 @@ class CustomField extends Model
})->first(); })->first();
} }
/**
* Checks the format of the attribute
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param $value string
* @since [v3.0]
* @return boolean
*/
public function check_format($value) public function check_format($value)
{ {
return preg_match('/^'.$this->attributes['format'].'$/', $value)===1; return preg_match('/^'.$this->attributes['format'].'$/', $value)===1;
} }
/**
* Gets the DB column name.
*
* @todo figure out if this is still needed? I don't know WTF it's for.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function db_column_name() public function db_column_name()
{ {
return $this->db_column; return $this->db_column;
@ -188,7 +231,7 @@ class CustomField extends Model
* *
* @author [A. Gianotto] [<snipe@snipe.net>] * @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4] * @since [v3.4]
* @return Array * @return string
*/ */
public function getFormatAttribute($value) public function getFormatAttribute($value)
{ {
@ -205,7 +248,7 @@ class CustomField extends Model
* *
* @author [A. Gianotto] [<snipe@snipe.net>] * @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4] * @since [v3.4]
* @return Array * @return array
*/ */
public function setFormatAttribute($value) public function setFormatAttribute($value)
{ {
@ -221,7 +264,7 @@ class CustomField extends Model
* *
* @author [A. Gianotto] [<snipe@snipe.net>] * @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4] * @since [v3.4]
* @return Array * @return array
*/ */
public function formatFieldValuesAsArray() public function formatFieldValuesAsArray()
{ {
@ -249,7 +292,7 @@ class CustomField extends Model
* *
* @author [A. Gianotto] [<snipe@snipe.net>] * @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4] * @since [v3.4]
* @return Boolean * @return boolean
*/ */
public function isFieldDecryptable($string) public function isFieldDecryptable($string)
{ {
@ -266,7 +309,7 @@ class CustomField extends Model
* *
* @author [A. Gianotto] [<snipe@snipe.net>] * @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4] * @since [v3.4]
* @return Boolean * @return boolean
*/ */
public function convertUnicodeDbSlug($original = null) public function convertUnicodeDbSlug($original = null)
{ {
@ -287,7 +330,7 @@ class CustomField extends Model
* @author [V. Cordes] [<volker@fdatek.de>] * @author [V. Cordes] [<volker@fdatek.de>]
* @param int $id * @param int $id
* @since [v4.1.10] * @since [v4.1.10]
* @return Array * @return array
*/ */
public function validationRules() public function validationRules()
{ {

View file

@ -22,23 +22,52 @@ class CustomFieldset extends Model
*/ */
protected $injectUniqueIdentifier = true; protected $injectUniqueIdentifier = true;
use ValidatingTrait; use ValidatingTrait;
/**
* Establishes the fieldset -> field relationship
*
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function fields() public function fields()
{ {
return $this->belongsToMany('\App\Models\CustomField')->withPivot(["required","order"])->orderBy("pivot_order"); return $this->belongsToMany('\App\Models\CustomField')->withPivot(["required","order"])->orderBy("pivot_order");
} }
/**
* Establishes the fieldset -> models relationship
*
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function models() public function models()
{ {
return $this->hasMany('\App\Models\AssetModel', "fieldset_id"); return $this->hasMany('\App\Models\AssetModel', "fieldset_id");
} }
/**
* Establishes the fieldset -> admin user relationship
*
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function user() public function user()
{ {
return $this->belongsTo('\App\Models\User'); //WARNING - not all CustomFieldsets have a User!! return $this->belongsTo('\App\Models\User'); //WARNING - not all CustomFieldsets have a User!!
} }
/**
* Determine the validation rules we should apply based on the
* custom field format
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return array
*/
public function validation_rules() public function validation_rules()
{ {
$rules=[]; $rules=[];

View file

@ -60,18 +60,27 @@ class Department extends SnipeModel
* *
* @var array * @var array
*/ */
protected $searchableRelations = []; protected $searchableRelations = [];
/**
* Establishes the department -> company relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company() public function company()
{ {
return $this->belongsTo('\App\Models\Company', 'company_id'); return $this->belongsTo('\App\Models\Company', 'company_id');
} }
/** /**
* Even though we allow allow for checkout to things beyond users * Establishes the department -> users relationship
* this method is an easy way of seeing if we are checked out to a user. *
* @return mixed * @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function users() public function users()
{ {
@ -80,15 +89,24 @@ class Department extends SnipeModel
/** /**
* Return the manager in charge of the dept * Establishes the department -> manager relationship
* @return mixed *
*/ * @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manager() public function manager()
{ {
return $this->belongsTo('\App\Models\User', 'manager_id'); return $this->belongsTo('\App\Models\User', 'manager_id');
} }
/**
* Establishes the department -> location relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location() public function location()
{ {
return $this->belongsTo('\App\Models\Location', 'location_id'); return $this->belongsTo('\App\Models\Location', 'location_id');

View file

@ -48,14 +48,28 @@ class Depreciation extends SnipeModel
*/ */
protected $searchableRelations = []; protected $searchableRelations = [];
/**
public function has_models() * Establishes the depreciation -> models relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v5.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function models()
{ {
return $this->hasMany('\App\Models\AssetModel', 'depreciation_id')->count(); return $this->hasMany('\App\Models\AssetModel', 'depreciation_id');
} }
public function has_licenses()
/**
* Establishes the depreciation -> licenses relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v5.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function licenses()
{ {
return $this->hasMany('\App\Models\License', 'depreciation_id')->count(); return $this->hasMany('\App\Models\License', 'depreciation_id');
} }
} }

View file

@ -37,17 +37,27 @@ class Group extends SnipeModel
* *
* @var array * @var array
*/ */
protected $searchableRelations = []; protected $searchableRelations = [];
/** /**
* Get user groups * Establishes the groups -> users relationship
*/ *
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function users() public function users()
{ {
return $this->belongsToMany('\App\Models\User', 'users_groups'); return $this->belongsToMany('\App\Models\User', 'users_groups');
} }
/**
* Decode JSON permissions into array
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return array
*/
public function decodePermissions() public function decodePermissions()
{ {
return json_decode($this->permissions, true); return json_decode($this->permissions, true);

View file

@ -110,8 +110,14 @@ class License extends Depreciable
protected $searchableRelations = [ protected $searchableRelations = [
'manufacturer' => ['name'], 'manufacturer' => ['name'],
'company' => ['name'], 'company' => ['name'],
]; ];
/**
* Update seat counts when the license is updated
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
*/
public static function boot() public static function boot()
{ {
parent::boot(); parent::boot();
@ -128,6 +134,13 @@ class License extends Depreciable
}); });
} }
/**
* Balance seat counts
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public static function adjustSeatCount($license, $oldSeats, $newSeats) public static function adjustSeatCount($license, $oldSeats, $newSeats)
{ {
// If the seats haven't changed, continue on happily. // If the seats haven't changed, continue on happily.
@ -181,15 +194,37 @@ class License extends Depreciable
return true; return true;
} }
/**
* Sets the attribute for whether or not the license is maintained
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return mixed
*/
public function setMaintainedAttribute($value) public function setMaintainedAttribute($value)
{ {
$this->attributes['maintained'] = filter_var($value, FILTER_VALIDATE_BOOLEAN); $this->attributes['maintained'] = filter_var($value, FILTER_VALIDATE_BOOLEAN);
} }
/**
* Sets the reassignable attribute
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return mixed
*/
public function setReassignableAttribute($value) public function setReassignableAttribute($value)
{ {
$this->attributes['reassignable'] = filter_var($value, FILTER_VALIDATE_BOOLEAN); $this->attributes['reassignable'] = filter_var($value, FILTER_VALIDATE_BOOLEAN);
} }
/**
* Sets expiration date attribute
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return mixed
*/
public function setExpirationDateAttribute($value) public function setExpirationDateAttribute($value)
{ {
@ -201,6 +236,13 @@ class License extends Depreciable
$this->attributes['expiration_date'] = $value; $this->attributes['expiration_date'] = $value;
} }
/**
* Sets termination date attribute
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return mixed
*/
public function setTerminationDateAttribute($value) public function setTerminationDateAttribute($value)
{ {
if ($value == '' || $value == '0000-00-00') { if ($value == '' || $value == '0000-00-00') {
@ -211,31 +253,74 @@ class License extends Depreciable
$this->attributes['termination_date'] = $value; $this->attributes['termination_date'] = $value;
} }
/**
* Establishes the license -> company relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company() public function company()
{ {
return $this->belongsTo('\App\Models\Company', 'company_id'); return $this->belongsTo('\App\Models\Company', 'company_id');
} }
/**
* Establishes the license -> category relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function category() public function category()
{ {
return $this->belongsTo('\App\Models\Category', 'category_id'); return $this->belongsTo('\App\Models\Category', 'category_id');
} }
/**
* Establishes the license -> manufacturer relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manufacturer() public function manufacturer()
{ {
return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id'); return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id');
} }
/**
* Determine whether the user should be emailed on checkin/checkout
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return boolean
*/
public function checkin_email() public function checkin_email()
{ {
return $this->category->checkin_email; return $this->category->checkin_email;
} }
/**
* Determine whether the user should be required to accept the license
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return boolean
*/
public function requireAcceptance() public function requireAcceptance()
{ {
return $this->category->require_acceptance; return $this->category->require_acceptance;
} }
/**
* Checks for a category-specific EULA, and if that doesn't exist,
* checks for a settings level EULA
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return string | false
*/
public function getEula() public function getEula()
{ {
$Parsedown = new \Parsedown(); $Parsedown = new \Parsedown();
@ -250,7 +335,11 @@ class License extends Depreciable
} }
/** /**
* Get the assigned user * Establishes the license -> assigned user relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function assignedusers() public function assignedusers()
{ {
@ -258,8 +347,12 @@ class License extends Depreciable
} }
/** /**
* Get asset logs for this asset * Establishes the license -> action logs relationship
*/ *
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetlog() public function assetlog()
{ {
return $this->hasMany('\App\Models\Actionlog', 'item_id') return $this->hasMany('\App\Models\Actionlog', 'item_id')
@ -268,8 +361,12 @@ class License extends Depreciable
} }
/** /**
* Get uploads for this asset * Establishes the license -> action logs -> uploads relationship
*/ *
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function uploads() public function uploads()
{ {
return $this->hasMany('\App\Models\Actionlog', 'item_id') return $this->hasMany('\App\Models\Actionlog', 'item_id')
@ -281,16 +378,26 @@ class License extends Depreciable
/** /**
* Get admin user for this asset * Establishes the license -> admin user relationship
*/ *
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser() public function adminuser()
{ {
return $this->belongsTo('\App\Models\User', 'user_id'); return $this->belongsTo('\App\Models\User', 'user_id');
} }
/** /**
* Get total licenses * Returns the total number of all license seats
*/ *
* @todo this can probably be refactored at some point. We don't need counting methods.
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return int
*/
public static function assetcount() public static function assetcount()
{ {
return LicenseSeat::whereNull('deleted_at') return LicenseSeat::whereNull('deleted_at')
@ -299,8 +406,14 @@ class License extends Depreciable
/** /**
* Get total licenses * Return the number of seats for this asset
*/ *
* @todo this can also probably be refactored at some point.
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function totalSeatsByLicenseID() public function totalSeatsByLicenseID()
{ {
return LicenseSeat::where('license_id', '=', $this->id) return LicenseSeat::where('license_id', '=', $this->id)
@ -308,12 +421,28 @@ class License extends Depreciable
->count(); ->count();
} }
// We do this to eager load the "count" of seats from the controller. Otherwise calling "count()" on each model results in n+1 /**
* Establishes the license -> seat relationship
*
* We do this to eager load the "count" of seats from the controller.
* Otherwise calling "count()" on each model results in n+1 sadness.
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function licenseSeatsRelation() public function licenseSeatsRelation()
{ {
return $this->hasMany(LicenseSeat::class)->whereNull('deleted_at')->selectRaw('license_id, count(*) as count')->groupBy('license_id'); return $this->hasMany(LicenseSeat::class)->whereNull('deleted_at')->selectRaw('license_id, count(*) as count')->groupBy('license_id');
} }
/**
* Sets the license seat count attribute
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return int
*/
public function getLicenseSeatsCountAttribute() public function getLicenseSeatsCountAttribute()
{ {
if ($this->licenseSeatsRelation->first()) { if ($this->licenseSeatsRelation->first()) {
@ -324,8 +453,12 @@ class License extends Depreciable
} }
/** /**
* Get total licenses not checked out * Returns the number of total available seats across all licenses
*/ *
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return int
*/
public static function availassetcount() public static function availassetcount()
{ {
return LicenseSeat::whereNull('assigned_to') return LicenseSeat::whereNull('assigned_to')
@ -335,7 +468,11 @@ class License extends Depreciable
} }
/** /**
* Get the number of available seats * Returns the number of total available seats for this license
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function availCount() public function availCount()
{ {
@ -345,6 +482,13 @@ class License extends Depreciable
->whereNull('deleted_at'); ->whereNull('deleted_at');
} }
/**
* Sets the available seats attribute
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return mixed
*/
public function getAvailSeatsCountAttribute() public function getAvailSeatsCountAttribute()
{ {
if ($this->availCount->first()) { if ($this->availCount->first()) {
@ -355,8 +499,11 @@ class License extends Depreciable
} }
/** /**
* Get the number of assigned seats * Retuns the number of assigned seats for this asset
* *
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function assignedCount() public function assignedCount()
{ {
@ -366,9 +513,15 @@ class License extends Depreciable
}); });
} }
/**
* Sets the assigned seats attribute
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return int
*/
public function getAssignedSeatsCountAttribute() public function getAssignedSeatsCountAttribute()
{ {
// dd($this->licenseSeatsRelation->first());
if ($this->assignedCount->first()) { if ($this->assignedCount->first()) {
return $this->assignedCount->first()->count; return $this->assignedCount->first()->count;
} }
@ -376,6 +529,13 @@ class License extends Depreciable
return 0; return 0;
} }
/**
* Calculates the number of remaining seats
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return int
*/
public function remaincount() public function remaincount()
{ {
$total = $this->licenseSeatsCount; $total = $this->licenseSeatsCount;
@ -385,7 +545,11 @@ class License extends Depreciable
} }
/** /**
* Get the total number of seats * Returns the total number of seats for this license
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return int
*/ */
public function totalcount() public function totalcount()
{ {
@ -396,21 +560,37 @@ class License extends Depreciable
} }
/** /**
* Get license seat data * Establishes the license -> seats relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function licenseseats() public function licenseseats()
{ {
return $this->hasMany('\App\Models\LicenseSeat'); return $this->hasMany('\App\Models\LicenseSeat');
} }
/**
* Establishes the license -> supplier relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function supplier() public function supplier()
{ {
return $this->belongsTo('\App\Models\Supplier', 'supplier_id'); return $this->belongsTo('\App\Models\Supplier', 'supplier_id');
} }
/*
* Get the next available free seat - used by /**
* Gets the next available free seat - used by
* the API to populate next_seat * the API to populate next_seat
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return mixed
*/ */
public function freeSeat() public function freeSeat()
{ {
@ -424,15 +604,28 @@ class License extends Depreciable
->first(); ->first();
} }
/*
* Get the next available free seat - used by /**
* the API to populate next_seat * Establishes the license -> free seats relationship
*/ *
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function freeSeats() public function freeSeats()
{ {
return $this->hasMany('\App\Models\LicenseSeat')->whereNull('assigned_to')->whereNull('deleted_at')->whereNull('asset_id'); return $this->hasMany('\App\Models\LicenseSeat')->whereNull('assigned_to')->whereNull('deleted_at')->whereNull('asset_id');
} }
/**
* Returns expiring licenses
*
* @todo should refactor. I don't like get() in model methods
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public static function getExpiringLicenses($days = 60) public static function getExpiringLicenses($days = 60)
{ {
@ -448,10 +641,10 @@ class License extends Depreciable
/** /**
* Query builder scope to order on manufacturer * Query builder scope to order on manufacturer
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderManufacturer($query, $order) public function scopeOrderManufacturer($query, $order)
{ {
@ -463,7 +656,7 @@ class License extends Depreciable
* Query builder scope to order on supplier * Query builder scope to order on supplier
* *
* @param \Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return \Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
@ -476,10 +669,10 @@ class License extends Depreciable
/** /**
* Query builder scope to order on company * Query builder scope to order on company
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param text $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderCompany($query, $order) public function scopeOrderCompany($query, $order)
{ {

View file

@ -28,21 +28,50 @@ class LicenseSeat extends Model implements ICompanyableChild
return ['asset', 'license']; return ['asset', 'license'];
} }
/**
* Establishes the seat -> license relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function license() public function license()
{ {
return $this->belongsTo('\App\Models\License', 'license_id'); return $this->belongsTo('\App\Models\License', 'license_id');
} }
/**
* Establishes the seat -> assignee relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function user() public function user()
{ {
return $this->belongsTo('\App\Models\User', 'assigned_to')->withTrashed(); return $this->belongsTo('\App\Models\User', 'assigned_to')->withTrashed();
} }
/**
* Establishes the seat -> asset relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function asset() public function asset()
{ {
return $this->belongsTo('\App\Models\Asset', 'asset_id')->withTrashed(); return $this->belongsTo('\App\Models\Asset', 'asset_id')->withTrashed();
} }
/**
* Determines the assigned seat's location based on user
* or asset its assigned to
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return string
*/
public function location() public function location()
{ {
if (($this->user) && ($this->user->location)) { if (($this->user) && ($this->user->location)) {

View file

@ -79,11 +79,25 @@ class Location extends SnipeModel
'parent' => ['name'] 'parent' => ['name']
]; ];
/**
* Establishes the location -> users relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function users() public function users()
{ {
return $this->hasMany('\App\Models\User', 'location_id'); return $this->hasMany('\App\Models\User', 'location_id');
} }
/**
* Establishes the location -> assets relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets() public function assets()
{ {
return $this->hasMany('\App\Models\Asset', 'location_id') return $this->hasMany('\App\Models\Asset', 'location_id')
@ -94,52 +108,103 @@ class Location extends SnipeModel
}); });
} }
/**
* Establishes the location -> asset's RTD relationship
*
* This used to have an ...->orHas() clause that referred to
* assignedAssets, and that was probably incorrect, as well as
* definitely was setting fire to the query-planner. So don't do that.
*
* It is arguable that we should have a '...->whereNull('assigned_to')
* bit in there, but that isn't always correct either (in the case
* where a user has no location, for example).
*
* In all likelihood, we need to denorm an "effective_location" column
* into Assets to make this slightly less miserable.
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function rtd_assets() public function rtd_assets()
{ {
/* This used to have an ...->orHas() clause that referred to /*
assignedAssets, and that was probably incorrect, as well as
definitely was setting fire to the query-planner. So don't do that.
It is arguable that we should have a '...->whereNull('assigned_to')
bit in there, but that isn't always correct either (in the case
where a user has no location, for example).
In all likelyhood, we need to denorm an "effective_location" column
into Assets to make this slightly less miserable.
*/ */
return $this->hasMany('\App\Models\Asset', 'rtd_location_id'); return $this->hasMany('\App\Models\Asset', 'rtd_location_id');
} }
/**
* Establishes the location -> parent location relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function parent() public function parent()
{ {
return $this->belongsTo('\App\Models\Location', 'parent_id','id'); return $this->belongsTo('\App\Models\Location', 'parent_id','id');
} }
/**
* Establishes the location -> manager relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manager() public function manager()
{ {
return $this->belongsTo('\App\Models\User', 'manager_id'); return $this->belongsTo('\App\Models\User', 'manager_id');
} }
/**
* Establishes the location -> child locations relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function childLocations() public function childLocations()
{ {
return $this->hasMany('\App\Models\Location', 'parent_id'); return $this->hasMany('\App\Models\Location', 'parent_id');
} }
// I don't think we need this anymore since we de-normed location_id in assets? /**
* Establishes the location -> assigned assets relationship
*
* I don't think we need this anymore since we de-normed location_id in assets?
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assignedAssets() public function assignedAssets()
{ {
return $this->morphMany('App\Models\Asset', 'assigned', 'assigned_type', 'assigned_to')->withTrashed(); return $this->morphMany('App\Models\Asset', 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
} }
/**
* Sets the location-specific OU attribute
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return mixed
*/
public function setLdapOuAttribute($ldap_ou) public function setLdapOuAttribute($ldap_ou)
{ {
return $this->attributes['ldap_ou'] = empty($ldap_ou) ? null : $ldap_ou; return $this->attributes['ldap_ou'] = empty($ldap_ou) ? null : $ldap_ou;
} }
/**
* Recursion to determine location hierarchy
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return mixed
*/
public static function getLocationHierarchy($locations, $parent_id = null) public static function getLocationHierarchy($locations, $parent_id = null)
{ {
$op = array(); $op = array();
foreach ($locations as $location) { foreach ($locations as $location) {
@ -163,7 +228,15 @@ class Location extends SnipeModel
return $op; return $op;
} }
/**
* Flattens the location array for display on the front-end
*
* @todo maybe move to presenters?
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public static function flattenLocationsArray($location_options_array = null) public static function flattenLocationsArray($location_options_array = null)
{ {
$location_options = array(); $location_options = array();
@ -193,14 +266,15 @@ class Location extends SnipeModel
/** /**
* Query builder scope to order on parent * Query builder scope to order on parent
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * We have to use a Left join here, or it will only return results with parents
* @param text $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderParent($query, $order) public function scopeOrderParent($query, $order)
{ {
// Left join here, or it will only return results with parents
return $query->leftJoin('locations as parent_loc', 'locations.parent_id', '=', 'parent_loc.id')->orderBy('parent_loc.name', $order); return $query->leftJoin('locations as parent_loc', 'locations.parent_id', '=', 'parent_loc.id')->orderBy('parent_loc.name', $order);
} }
@ -208,7 +282,7 @@ class Location extends SnipeModel
* Query builder scope to order on manager name * Query builder scope to order on manager name
* *
* @param \Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return \Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */

View file

@ -66,11 +66,6 @@ class Manufacturer extends SnipeModel
public function has_models()
{
return $this->hasMany('\App\Models\AssetModel', 'manufacturer_id')->count();
}
public function assets() public function assets()
{ {
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'manufacturer_id', 'model_id'); return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'manufacturer_id', 'model_id');

View file

@ -50,19 +50,28 @@ class Statuslabel extends SnipeModel
* *
* @var array * @var array
*/ */
protected $searchableRelations = []; protected $searchableRelations = [];
/** /**
* Get assets with associated status label * Establishes the status label -> assets relationship
* *
* @return \Illuminate\Support\Collection * @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function assets() public function assets()
{ {
return $this->hasMany('\App\Models\Asset', 'status_id'); return $this->hasMany('\App\Models\Asset', 'status_id');
} }
/**
* Gets the status label type
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return string
*/
public function getStatuslabelType() public function getStatuslabelType()
{ {
@ -78,6 +87,11 @@ class Statuslabel extends SnipeModel
} }
/**
* Query builder scope to for pending status types
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopePending() public function scopePending()
{ {
return $this->where('pending', '=', 1) return $this->where('pending', '=', 1)
@ -85,6 +99,11 @@ class Statuslabel extends SnipeModel
->where('deployable', '=', 0); ->where('deployable', '=', 0);
} }
/**
* Query builder scope for archived status types
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeArchived() public function scopeArchived()
{ {
return $this->where('pending', '=', 0) return $this->where('pending', '=', 0)
@ -92,6 +111,11 @@ class Statuslabel extends SnipeModel
->where('deployable', '=', 0); ->where('deployable', '=', 0);
} }
/**
* Query builder scope for deployable status types
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeDeployable() public function scopeDeployable()
{ {
return $this->where('pending', '=', 0) return $this->where('pending', '=', 0)
@ -99,7 +123,13 @@ class Statuslabel extends SnipeModel
->where('deployable', '=', 1); ->where('deployable', '=', 1);
} }
/**
* Helper function to determine type attributes
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return string
*/
public static function getStatuslabelTypesForDB($type) public static function getStatuslabelTypesForDB($type)
{ {

View file

@ -66,13 +66,30 @@ class Supplier extends SnipeModel
protected $fillable = ['name','address','address2','city','state','country','zip','phone','fax','email','contact','url','notes']; protected $fillable = ['name','address','address2','city','state','country','zip','phone','fax','email','contact','url','notes'];
// Eager load counts. /**
// We do this to eager load the "count" of seats from the controller. Otherwise calling "count()" on each model results in n+1 * Eager load counts
*
* We do this to eager load the "count" of seats from the controller.
* Otherwise calling "count()" on each model results in n+1.
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetsRelation() public function assetsRelation()
{ {
return $this->hasMany(Asset::class)->whereNull('deleted_at')->selectRaw('supplier_id, count(*) as count')->groupBy('supplier_id'); return $this->hasMany(Asset::class)->whereNull('deleted_at')->selectRaw('supplier_id, count(*) as count')->groupBy('supplier_id');
} }
/**
* Sets the license seat count attribute
*
* @todo I don't see the licenseSeatsRelation here?
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function getLicenseSeatsCountAttribute() public function getLicenseSeatsCountAttribute()
{ {
if ($this->licenseSeatsRelation->first()) { if ($this->licenseSeatsRelation->first()) {
@ -81,21 +98,50 @@ class Supplier extends SnipeModel
return 0; return 0;
} }
/**
* Establishes the supplier -> assets relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets() public function assets()
{ {
return $this->hasMany('\App\Models\Asset', 'supplier_id'); return $this->hasMany('\App\Models\Asset', 'supplier_id');
} }
/**
* Establishes the supplier -> accessories relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function accessories() public function accessories()
{ {
return $this->hasMany('\App\Models\Accessory', 'supplier_id'); return $this->hasMany('\App\Models\Accessory', 'supplier_id');
} }
/**
* Establishes the supplier -> asset maintenances relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function asset_maintenances() public function asset_maintenances()
{ {
return $this->hasMany('\App\Models\AssetMaintenance', 'supplier_id'); return $this->hasMany('\App\Models\AssetMaintenance', 'supplier_id');
} }
/**
* Return the number of assets by supplier
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return int
*/
public function num_assets() public function num_assets()
{ {
if ($this->assetsRelation->first()) { if ($this->assetsRelation->first()) {
@ -105,16 +151,39 @@ class Supplier extends SnipeModel
return 0; return 0;
} }
/**
* Establishes the supplier -> license relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function licenses() public function licenses()
{ {
return $this->hasMany('\App\Models\License', 'supplier_id'); return $this->hasMany('\App\Models\License', 'supplier_id');
} }
/**
* Return the number of licenses by supplier
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return int
*/
public function num_licenses() public function num_licenses()
{ {
return $this->licenses()->count(); return $this->licenses()->count();
} }
/**
* Add http to the url in suppliers if the user didn't give one
*
* @todo this should be handled via validation, no?
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function addhttp($url) public function addhttp($url)
{ {
if (!preg_match("~^(?:f|ht)tps?://~i", $url)) { if (!preg_match("~^(?:f|ht)tps?://~i", $url)) {

View file

@ -1,14 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Throttle extends Model
{
protected $table = 'throttle';
public function user()
{
return $this->belongsTo('User', 'user_id');
}
}

View file

@ -100,8 +100,18 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
'department' => ['name'], 'department' => ['name'],
'groups' => ['name'], 'groups' => ['name'],
'manager' => ['first_name', 'last_name', 'username'] 'manager' => ['first_name', 'last_name', 'username']
]; ];
/**
* Check user permissions
*
* Parses the user and group permission masks to see if the user
* is authorized to do the thing
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return boolean
*/
public function hasAccess($section) public function hasAccess($section)
{ {
if ($this->isSuperUser()) { if ($this->isSuperUser()) {
@ -136,6 +146,13 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
return false; return false;
} }
/**
* Checks if the user is a SuperUser
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return boolean
*/
public function isSuperUser() public function isSuperUser()
{ {
if (!$user_permissions = json_decode($this->permissions, true)) { if (!$user_permissions = json_decode($this->permissions, true)) {
@ -158,26 +175,63 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
} }
/**
* Establishes the user -> company relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function company() public function company()
{ {
return $this->belongsTo('\App\Models\Company', 'company_id'); return $this->belongsTo('\App\Models\Company', 'company_id');
} }
/**
* Establishes the user -> department relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function department() public function department()
{ {
return $this->belongsTo('\App\Models\Department', 'department_id'); return $this->belongsTo('\App\Models\Department', 'department_id');
} }
/**
* Checks activated status
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return boolean
*/
public function isActivated() public function isActivated()
{ {
return $this->activated ==1; return $this->activated ==1;
} }
/**
* Returns the full name attribute
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return string
*/
public function getFullNameAttribute() public function getFullNameAttribute()
{ {
return $this->first_name . " " . $this->last_name; return $this->first_name . " " . $this->last_name;
} }
/**
* Returns the complete name attribute with username
*
* @todo refactor this so it's less repetitive and dumb
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return string
*/
public function getCompleteNameAttribute() public function getCompleteNameAttribute()
{ {
return $this->last_name . ", " . $this->first_name . " (" . $this->username . ")"; return $this->last_name . ", " . $this->first_name . " (" . $this->username . ")";
@ -198,7 +252,11 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
/** /**
* Get assets assigned to this user * Establishes the user -> assets relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function assets() public function assets()
{ {
@ -206,7 +264,14 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
} }
/** /**
* Get assets assigned to this user * Establishes the user -> maintenances relationship
*
* This would only be used to return maintenances that this user
* created.
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function assetmaintenances() public function assetmaintenances()
{ {
@ -214,7 +279,11 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
} }
/** /**
* Get accessories assigned to this user * Establishes the user -> accessories relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function accessories() public function accessories()
{ {
@ -222,7 +291,11 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
} }
/** /**
* Get consumables assigned to this user * Establishes the user -> consumables relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function consumables() public function consumables()
{ {
@ -230,7 +303,11 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
} }
/** /**
* Get licenses assigned to this user * Establishes the user -> license seats relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function licenses() public function licenses()
{ {
@ -238,78 +315,105 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
} }
/** /**
* Get action logs for this user * Establishes the user -> actionlogs relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function userlog() public function userlog()
{ {
return $this->hasMany('\App\Models\Actionlog', 'target_id')->orderBy('created_at', 'DESC')->withTrashed(); return $this->hasMany('\App\Models\Actionlog', 'target_id')->orderBy('created_at', 'DESC')->withTrashed();
} }
/** /**
* Establishes the user -> location relationship
*
* Get the asset's location based on the assigned user * Get the asset's location based on the assigned user
* @todo - this should be removed once we're sure we've switched it *
* to location() * @todo - this should be removed once we're sure we've switched it to location()
**/ *
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function userloc() public function userloc()
{ {
return $this->belongsTo('\App\Models\Location', 'location_id')->withTrashed(); return $this->belongsTo('\App\Models\Location', 'location_id')->withTrashed();
} }
/** /**
* Get the asset's location based on the assigned user * Establishes the user -> location relationship
**/ *
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function location() public function location()
{ {
return $this->belongsTo('\App\Models\Location', 'location_id')->withTrashed(); return $this->belongsTo('\App\Models\Location', 'location_id')->withTrashed();
} }
/** /**
* Get the user's manager based on the assigned user * Establishes the user -> manager relationship
**/ *
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manager() public function manager()
{ {
return $this->belongsTo('\App\Models\User', 'manager_id')->withTrashed(); return $this->belongsTo('\App\Models\User', 'manager_id')->withTrashed();
} }
/** /**
* Get any locations the user manages. * Establishes the user -> managed locations relationship
**/ *
* @author A. Gianotto <snipe@snipe.net>
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function managedLocations() public function managedLocations()
{ {
return $this->hasMany('\App\Models\Location', 'manager_id')->withTrashed(); return $this->hasMany('\App\Models\Location', 'manager_id')->withTrashed();
} }
/** /**
* Get user groups * Establishes the user -> groups relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function groups() public function groups()
{ {
return $this->belongsToMany('\App\Models\Group', 'users_groups'); return $this->belongsToMany('\App\Models\Group', 'users_groups');
} }
/**
public function accountStatus() * Establishes the user -> assets relationship
{ *
if ($this->throttle) { * @author A. Gianotto <snipe@snipe.net>
if ($this->throttle->suspended==1) { * @since [v4.0]
return 'suspended'; * @return \Illuminate\Database\Eloquent\Relations\Relation
} elseif ($this->throttle->banned==1) { */
return 'banned';
} else {
return false;
}
} else {
return false;
}
}
public function assetlog() public function assetlog()
{ {
return $this->hasMany('\App\Models\Asset', 'id')->withTrashed(); return $this->hasMany('\App\Models\Asset', 'id')->withTrashed();
} }
/** /**
* Get uploads for this asset * Establishes the user -> uploads relationship
*
* @todo I don't think we use this?
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function uploads() public function uploads()
{ {
@ -321,28 +425,54 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
} }
/** /**
* Fetch Items User has requested * Establishes the user -> requested assets relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function checkoutRequests() public function checkoutRequests()
{ {
return $this->belongsToMany(Asset::class, 'checkout_requests', 'user_id', 'requestable_id')->whereNull('canceled_at'); return $this->belongsToMany(Asset::class, 'checkout_requests', 'user_id', 'requestable_id')->whereNull('canceled_at');
} }
public function throttle() /**
{ * Query builder scope to return deleted users
return $this->hasOne('\App\Models\Throttle'); * @author A. Gianotto <snipe@snipe.net>
} * @since [v2.0]
*
* @param string $query
* @return \Illuminate\Database\Query\Builder
*/
public function scopeGetDeleted($query) public function scopeGetDeleted($query)
{ {
return $query->withTrashed()->whereNotNull('deleted_at'); return $query->withTrashed()->whereNotNull('deleted_at');
} }
/**
* Query builder scope to return NOT-deleted users
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
*
* @param string $query
* @return \Illuminate\Database\Query\Builder
*/
public function scopeGetNotDeleted($query) public function scopeGetNotDeleted($query)
{ {
return $query->whereNull('deleted_at'); return $query->whereNull('deleted_at');
} }
/**
* Query builder scope to return users by email or username
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
*
* @param string $query
* @param string $user_username
* @param string $user_email
* @return \Illuminate\Database\Query\Builder
*/
public function scopeMatchEmailOrUsername($query, $user_username, $user_email) public function scopeMatchEmailOrUsername($query, $user_username, $user_email)
{ {
return $query->where('email', '=', $user_email) return $query->where('email', '=', $user_email)
@ -350,6 +480,15 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
->orWhere('username', '=', $user_email); ->orWhere('username', '=', $user_email);
} }
/**
* Generate email from full name
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
*
* @param string $query
* @return string
*/
public static function generateEmailFromFullName($name) public static function generateEmailFromFullName($name)
{ {
$username = User::generateFormattedNameFromFullName($name, Setting::getSettings()->email_format); $username = User::generateFormattedNameFromFullName($name, Setting::getSettings()->email_format);
@ -422,9 +561,9 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
/** /**
* Run additional, advanced searches. * Run additional, advanced searches.
* *
* @param Illuminate\Database\Eloquent\Builder $query * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param array $term The search terms * @param array $terms The search terms
* @return Illuminate\Database\Eloquent\Builder * @return \Illuminate\Database\Eloquent\Builder
*/ */
public function advancedTextSearch(Builder $query, array $terms) { public function advancedTextSearch(Builder $query, array $terms) {
@ -435,7 +574,13 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
return $query; return $query;
} }
/**
* Query builder scope to return users by group
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param int $id
* @return \Illuminate\Database\Query\Builder
*/
public function scopeByGroup($query, $id) { public function scopeByGroup($query, $id) {
return $query->whereHas('groups', function ($query) use ($id) { return $query->whereHas('groups', function ($query) use ($id) {
$query->where('groups.id', '=', $id); $query->where('groups.id', '=', $id);
@ -445,9 +590,8 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
/** /**
* Query builder scope for Deleted users * Query builder scope for Deleted users
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* * @return \Illuminate\Database\Query\Builder Modified query builder
* @return Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeDeleted($query) public function scopeDeleted($query)
@ -459,10 +603,10 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
/** /**
* Query builder scope to order on manager * Query builder scope to order on manager
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderManager($query, $order) public function scopeOrderManager($query, $order)
{ {
@ -473,10 +617,10 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
/** /**
* Query builder scope to order on company * Query builder scope to order on company
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderLocation($query, $order) public function scopeOrderLocation($query, $order)
{ {
@ -487,10 +631,10 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
/** /**
* Query builder scope to order on department * Query builder scope to order on department
* *
* @param Illuminate\Database\Query\Builder $query Query builder instance * @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order * @param string $order Order
* *
* @return Illuminate\Database\Query\Builder Modified query builder * @return \Illuminate\Database\Query\Builder Modified query builder
*/ */
public function scopeOrderDepartment($query, $order) public function scopeOrderDepartment($query, $order)
{ {

View file

@ -34,7 +34,7 @@ class CategoryTest extends BaseTest
$category = $this->createValidCategory('asset-desktop-category'); $category = $this->createValidCategory('asset-desktop-category');
$models = factory(App\Models\AssetModel::class, 5)->states('mbp-13-model')->create(['category_id' => $category->id]); $models = factory(App\Models\AssetModel::class, 5)->states('mbp-13-model')->create(['category_id' => $category->id]);
$this->assertEquals(5, $category->has_models()); $this->assertEquals(5, $category->models->count());
$this->assertCount(5, $category->models); $this->assertCount(5, $category->models);
$models->each(function($model) { $models->each(function($model) {

View file

@ -32,7 +32,7 @@ class DepreciationTest extends BaseTest
$this->createValidAssetModel(); $this->createValidAssetModel();
$depreciation = $this->createValidDepreciation('computer', ['name' => 'New Depreciation']); $depreciation = $this->createValidDepreciation('computer', ['name' => 'New Depreciation']);
$models = factory(App\Models\AssetModel::class, 5)->states('mbp-13-model')->create(['depreciation_id'=>$depreciation->id]); $models = factory(App\Models\AssetModel::class, 5)->states('mbp-13-model')->create(['depreciation_id'=>$depreciation->id]);
$this->assertEquals(5,$depreciation->has_models()); $this->assertEquals(5,$depreciation->models->count());
} }
public function testADepreciationHasLicenses() public function testADepreciationHasLicenses()