ba51021ce3
commit818db58a7bMerge:baf14c43ec4f900e9aAuthor: snipe <snipe@snipe.net> Date: Wed Jan 4 13:22:03 2023 -0800 Merge pull request #12305 from uberbrady/fix_license_seat_reporting Fixed: Change license_seat changing method to properly 'true up' license seats commitc4f900e9afAuthor: Brady Wetherington <bwetherington@grokability.com> Date: Wed Jan 4 13:02:53 2023 -0800 Change license_seat changing method to properly 'true up' license seats commitbaf14c43eeMerge:d187174f0fa439a192Author: snipe <snipe@snipe.net> Date: Tue Jan 3 14:50:25 2023 -0800 Merge pull request #12298 from snipe/fixes/db_seeder_company_id Fixed db seeder when company id is not present commitfa439a1928Author: snipe <snipe@snipe.net> Date: Tue Jan 3 14:45:23 2023 -0800 Check that the array key exists before trying to seed it Signed-off-by: snipe <snipe@snipe.net> commitd187174f00Merge:6d3c5e06592ae27129Author: snipe <snipe@snipe.net> Date: Thu Dec 22 11:29:12 2022 -0800 Merge pull request #12090 from Godmartinz/deparmtnet_name_validator Added: validation for department names at Company locations commit6d3c5e0659Merge:685cc86d7e791e6592Author: snipe <snipe@snipe.net> Date: Wed Dec 21 19:04:11 2022 -0800 Merge pull request #12264 from Godmartinz/gh12253_display_notes_accessories Added: notes to the accessories tab for user detail view commit685cc86d71Author: snipe <snipe@snipe.net> Date: Tue Dec 20 17:24:01 2022 -0800 Sets the `ldap_default_group` field to nullable and default null Signed-off-by: snipe <snipe@snipe.net> commitfb10a6f218Merge:128c21a903a9b8a499Author: snipe <snipe@snipe.net> Date: Tue Dec 20 17:05:18 2022 -0800 Merge pull request #12268 from inietov/fixes/people_count Fixed: Dashboard user count scoping when full company support is enabled commit3a9b8a4993Author: Ivan Nieto Vivanco <inietov@gmail.com> Date: Tue Dec 20 18:39:17 2022 -0600 Calculate the proper amount of people in the dashboard if Full Company Support is enabled commit128c21a905Merge:88291cadc75a757d6fAuthor: snipe <snipe@snipe.net> Date: Tue Dec 20 15:09:30 2022 -0800 Merge pull request #12266 from uberbrady/fix-select-all-bug Fixed: There was a bug with BS tables' select-all which showed an incorrect list of elements commit75a757d6f5Author: Brady Wetherington <bwetherington@grokability.com> Date: Tue Dec 20 14:57:58 2022 -0800 There was a bug with select-all where some bits didn't quite work commite791e6592aAuthor: Godfrey M <godmartinz@gmail.com> Date: Tue Dec 20 10:37:19 2022 -0800 adds notes to the accessories tab under users commit88291cadc1Merge:399c7590c94afe2bc6Author: snipe <snipe@snipe.net> Date: Mon Dec 19 12:41:32 2022 -0800 Merge pull request #12254 from akemidx/documentating_something Commenting on a scope in Models/Company.php commit94afe2bc6aAuthor: akemidx <kojotek.dx@gmail.com> Date: Mon Dec 19 14:48:43 2022 -0500 edits & typo fixes commit399c7590cdMerge:d0c5ba70feb67d1b06Author: snipe <snipe@snipe.net> Date: Thu Dec 15 14:19:41 2022 -0800 Merge pull request #12209 from snipe/fixes/error_downloading_unaccepted_assets Fixed 500 when downloading the Unaccepted Assets report [sc-19555] commitd0c5ba70f6Merge:29c2ff56ed9a21cce0Author: snipe <snipe@snipe.net> Date: Thu Dec 15 12:42:29 2022 -0800 Merge pull request #12242 from inietov/features/add_purchase_cost_column Added `purchase_cost` to user's default view [sc-19680] commit133d6ffa50Author: akemidx <kojotek.dx@gmail.com> Date: Thu Dec 15 15:18:24 2022 -0500 Commenting on a scope in Models/Company.php commitd9a21cce00Author: Ivan Nieto Vivanco <inietov@gmail.com> Date: Thu Dec 15 14:12:05 2022 -0600 Add other items' purchase_cost columns to the same permission commit29c2ff56ecMerge:3e7975b2c1fe0bfe17Author: snipe <snipe@snipe.net> Date: Thu Dec 15 11:26:49 2022 -0800 Merge pull request #12188 from snipe/fixes/decrease_logging_for_saml_when_not_enabled Removed extra logging case that was very noisy commit3e7975b2c3Merge:227fef76ed870bc3b0Author: snipe <snipe@snipe.net> Date: Thu Dec 15 11:25:53 2022 -0800 Merge pull request #12250 from akemidx/grey_out_pw_reset_button Fixed: Grey out pw reset button for consistency commitd870bc3b02Author: akemidx <kojotek.dx@gmail.com> Date: Thu Dec 15 14:19:51 2022 -0500 nested if loop commit227fef76eeMerge:418ddcfac9d44720ffAuthor: snipe <snipe@snipe.net> Date: Thu Dec 15 11:06:53 2022 -0800 Merge pull request #11736 from Godmartinz/gh6508_ldap_default_group Adds a permission group selection for directory sync commit9d44720ffdAuthor: Godfrey M <godmartinz@gmail.com> Date: Thu Dec 15 11:02:34 2022 -0800 reverted changes to composer.lock commit9f3f0a25edAuthor: Godfrey M <godmartinz@gmail.com> Date: Thu Dec 15 10:53:45 2022 -0800 reverted changes to composer.lock commit2e228ccb0bAuthor: Godfrey M <godmartinz@gmail.com> Date: Thu Dec 15 10:45:42 2022 -0800 redid a few things. should be good now :) commit3ee413f379Author: Godfrey M <godmartinz@gmail.com> Date: Thu Dec 15 09:20:30 2022 -0800 removes livewire stuff commitb142f8e012Author: Ivan Nieto Vivanco <inietov@gmail.com> Date: Wed Dec 14 23:00:35 2022 -0600 Add the permission to show purchase cost column to non-admin sessions commit418ddcfac3Merge:c342668f01a908e361Author: snipe <snipe@snipe.net> Date: Wed Dec 14 17:46:53 2022 -0800 Merge pull request #9876 from Toreg87/fixes/locations-deletable Fixed #9875: Make locations deletable for non Superuser-Accounts with FullMultipleCompanySupport commitc342668f0fAuthor: snipe <snipe@snipe.net> Date: Wed Dec 14 17:25:39 2022 -0800 Update @scoo73r as a contributor commit2f6a26ec7dAuthor: snipe <snipe@snipe.net> Date: Wed Dec 14 17:25:25 2022 -0800 Add @scoo73r as a contributor commitf635278010Merge:d13a237008043b8678Author: snipe <snipe@snipe.net> Date: Wed Dec 14 16:42:41 2022 -0800 Merge pull request #12251 from snipe/security/upgrade_font_awesome Upgraded font awesome to 6.2.1 commit8043b86786Author: snipe <snipe@snipe.net> Date: Wed Dec 14 16:41:56 2022 -0800 Upgraded font awesome to 6.2.1 Signed-off-by: snipe <snipe@snipe.net> commitd13a237000Merge:fabefa61bd0d0058e7Author: snipe <snipe@snipe.net> Date: Wed Dec 14 12:13:18 2022 -0800 Merge pull request #12205 from Godmartinz/sc19675_add_remote_to_importer Adds remote field to the user importer commitb114ffd2c3Author: akemidx <kojotek.dx@gmail.com> Date: Wed Dec 14 14:48:59 2022 -0500 Grey out button pw reset button for consistency When user has no email in their profile, the box is greyed out for consistency accross all buttons on the user profile commitfabefa61b0Merge:389ec3a3cf3e57d7dcAuthor: snipe <snipe@snipe.net> Date: Tue Dec 13 14:00:48 2022 -0800 Merge pull request #12243 from akemidx/new_grey_out_when_no_assets Created method in users.php for adding up all assigned to user and pr… commitf3e57d7dc0Author: akemidx <kojotek.dx@gmail.com> Date: Tue Dec 13 16:00:59 2022 -0500 fixing PR commit389ec3a3cbMerge:c432fb9d76a72c344bAuthor: snipe <snipe@snipe.net> Date: Tue Dec 13 12:57:50 2022 -0800 Merge pull request #12247 from Godmartinz/gh12225_serial_added_to_components adds serial to components tab of assets commit6a72c344b7Author: Godfrey M <godmartinz@gmail.com> Date: Tue Dec 13 12:32:30 2022 -0800 removed the cuddlers commit4442b446b9Author: Godfrey M <godmartinz@gmail.com> Date: Tue Dec 13 10:30:37 2022 -0800 adds serial to components tab of assets commitc432fb9d70Merge:9e8fff6e5fa872b09aAuthor: snipe <snipe@snipe.net> Date: Tue Dec 13 10:28:17 2022 -0800 Merge pull request #12181 from Godmartinz/gh12163_asset_age Adds asset age to asset index and asset view pages commit07ae91b00fAuthor: akemi <akemi@ShibaPro.local> Date: Wed Dec 7 17:46:18 2022 -0500 Created method in users.php for adding up all assigned to user and providing an integer value. this then used to grey out buttons on user view if user has nothing assigned. commit450ad3dcecAuthor: Ivan Nieto Vivanco <inietov@gmail.com> Date: Mon Dec 12 14:17:08 2022 -0600 Added the column purchase_cost to user's default view commitfa872b09a9Author: Godfrey M <godmartinz@gmail.com> Date: Mon Dec 12 10:38:31 2022 -0800 fixes a typo, the world is great again commiteb67d1b064Author: Ivan Nieto Vivanco <inietov@gmail.com> Date: Tue Dec 6 18:00:16 2022 -0600 Filter items from the report if null returned commitd0d0058e79Author: Godfrey M <godmartinz@gmail.com> Date: Tue Dec 6 11:19:28 2022 -0800 removed unwanted changes commitbbd04f8876Author: Godfrey M <godmartinz@gmail.com> Date: Tue Dec 6 11:13:24 2022 -0800 adds the rest of the fields for Remote commit36901d271bAuthor: Godfrey M <godmartinz@gmail.com> Date: Mon Dec 5 16:28:19 2022 -0800 adds csvmatch for remote. Im a bit lost though lol commit3206929ee4Author: Godfrey M <godmartinz@gmail.com> Date: Tue Nov 29 09:51:42 2022 -0800 adds AgeFormatter, not working yet commit1fe0bfe17eAuthor: snipe <snipe@snipe.net> Date: Mon Nov 28 19:27:42 2022 -0800 Removed extra logging case that was very noisy Signed-off-by: snipe <snipe@snipe.net> commit8d861cfd82Author: Godfrey M <godmartinz@gmail.com> Date: Mon Nov 28 10:59:18 2022 -0800 adds age to the asset table commit078e7281cdAuthor: Godfrey M <godmartinz@gmail.com> Date: Mon Nov 28 10:45:58 2022 -0800 adds asset age to asset view commit92ae271292Author: Godfrey M <godmartinz@gmail.com> Date: Wed Nov 9 13:11:33 2022 -0800 adds validation for department names at Company locations commitf2d4a61e3cAuthor: Godfrey M <godmartinz@gmail.com> Date: Tue Oct 18 15:31:37 2022 -0700 removes dead space commit3f25a1bf61Author: Godfrey M <godmartinz@gmail.com> Date: Tue Oct 18 15:25:38 2022 -0700 removes dead code commitf9ac447dd1Merge:9b448227fb7bcfacccAuthor: Godfrey M <godmartinz@gmail.com> Date: Tue Oct 18 15:18:09 2022 -0700 adds default group to LDAP commit9b448227f7Author: Godfrey M <godmartinz@gmail.com> Date: Tue Sep 13 11:40:10 2022 -0700 tinkering to no avail commit28bc97f29fAuthor: Godfrey M <godmartinz@gmail.com> Date: Mon Sep 12 11:40:16 2022 -0700 one line away from this being over with commit193b31e427Author: Godfrey M <godmartinz@gmail.com> Date: Wed Aug 31 12:58:33 2022 -0700 select options working, testing sync then done commit70ac8af9c4Author: Godfrey M <godmartinz@gmail.com> Date: Wed Aug 31 09:53:20 2022 -0700 . commit0c362e8b57Author: Godfrey M <godmartinz@gmail.com> Date: Mon Aug 29 12:09:56 2022 -0700 gets the groups selector to appear but options are blank commitfc6fefdb4eAuthor: Godfrey M <godmartinz@gmail.com> Date: Thu Aug 25 15:19:38 2022 -0700 adds migration, variables, checkbox,working on groups commit1a908e361eAuthor: Tobias Regnery <tobias.regnery@gmail.com> Date: Thu Jul 29 10:33:34 2021 +0200 Make locations deletable for non Superuser-Accounts with FullMultipleCompanySupport locations->isDeletable() checks via gate::allows if a locations is deletable. This calls SnipePermissionsPolicy->before() and checks for !Company::isCurrentUserHasAccess($item). This returns false because locations don't have a company_id. Check for this and return true if the item don't have a company_id. Signed-off-by: snipe <snipe@snipe.net>
707 lines
20 KiB
PHP
Executable File
707 lines
20 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Helpers\Helper;
|
|
use App\Models\Traits\Searchable;
|
|
use App\Presenters\Presentable;
|
|
use Carbon\Carbon;
|
|
use DB;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Session;
|
|
use Watson\Validating\ValidatingTrait;
|
|
|
|
class License extends Depreciable
|
|
{
|
|
use HasFactory;
|
|
|
|
protected $presenter = \App\Presenters\LicensePresenter::class;
|
|
|
|
use SoftDeletes;
|
|
use CompanyableTrait;
|
|
use Loggable, Presentable;
|
|
protected $injectUniqueIdentifier = true;
|
|
use ValidatingTrait;
|
|
|
|
// We set these as protected dates so that they will be easily accessible via Carbon
|
|
|
|
public $timestamps = true;
|
|
|
|
protected $guarded = 'id';
|
|
protected $table = 'licenses';
|
|
|
|
protected $casts = [
|
|
'purchase_date' => 'datetime',
|
|
'expiration_date' => 'datetime',
|
|
'termination_date' => 'datetime',
|
|
'seats' => 'integer',
|
|
'category_id' => 'integer',
|
|
'company_id' => 'integer',
|
|
];
|
|
|
|
protected $rules = [
|
|
'name' => 'required|string|min:3|max:255',
|
|
'seats' => 'required|min:1|integer',
|
|
'license_email' => 'email|nullable|max:120',
|
|
'license_name' => 'string|nullable|max:100',
|
|
'notes' => 'string|nullable',
|
|
'category_id' => 'required|exists:categories,id',
|
|
'company_id' => 'integer|nullable',
|
|
'purchase_cost'=> 'numeric|nullable|gte:0',
|
|
];
|
|
|
|
/**
|
|
* The attributes that are mass assignable.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $fillable = [
|
|
'company_id',
|
|
'depreciation_id',
|
|
'expiration_date',
|
|
'license_email',
|
|
'license_name', //actually licensed_to
|
|
'maintained',
|
|
'manufacturer_id',
|
|
'category_id',
|
|
'name',
|
|
'notes',
|
|
'order_number',
|
|
'purchase_cost',
|
|
'purchase_date',
|
|
'purchase_order',
|
|
'reassignable',
|
|
'seats',
|
|
'serial',
|
|
'supplier_id',
|
|
'termination_date',
|
|
'user_id',
|
|
];
|
|
|
|
use Searchable;
|
|
|
|
/**
|
|
* The attributes that should be included when searching the model.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $searchableAttributes = [
|
|
'name',
|
|
'serial',
|
|
'notes',
|
|
'order_number',
|
|
'purchase_order',
|
|
'purchase_cost',
|
|
'purchase_date',
|
|
'expiration_date',
|
|
];
|
|
|
|
/**
|
|
* The relations and their attributes that should be included when searching the model.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $searchableRelations = [
|
|
'manufacturer' => ['name'],
|
|
'company' => ['name'],
|
|
'category' => ['name'],
|
|
'depreciation' => ['name'],
|
|
];
|
|
|
|
/**
|
|
* Update seat counts when the license is updated
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v3.0]
|
|
*/
|
|
public static function boot()
|
|
{
|
|
parent::boot();
|
|
// We need to listen for created for the initial setup so that we have a license ID.
|
|
static::created(function ($license) {
|
|
$newSeatCount = $license->getAttributes()['seats'];
|
|
|
|
return static::adjustSeatCount($license, 0, $newSeatCount);
|
|
});
|
|
// However, we listen for updating to be able to prevent the edit if we cannot delete enough seats.
|
|
static::updating(function ($license) {
|
|
$newSeatCount = $license->getAttributes()['seats'];
|
|
//$oldSeatCount = isset($license->getOriginal()['seats']) ? $license->getOriginal()['seats'] : 0;
|
|
/*
|
|
That previous method *did* mostly work, but if you ever managed to get your $license->seats value out of whack
|
|
with your actual count of license_seats *records*, you would never manage to get back 'into whack'.
|
|
The below method actually grabs a count of existing license_seats records, so it will be more accurate.
|
|
This means that if your license_seats are out of whack, you can change the quantity and hit 'save' and it
|
|
will manage to 'true up' and make your counts line up correctly.
|
|
*/
|
|
$oldSeatCount = $license->license_seats_count;
|
|
|
|
return static::adjustSeatCount($license, $oldSeatCount, $newSeatCount);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 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)
|
|
{
|
|
// If the seats haven't changed, continue on happily.
|
|
if ($oldSeats == $newSeats) {
|
|
return true;
|
|
}
|
|
// On Create, we just make one for each of the seats.
|
|
$change = abs($oldSeats - $newSeats);
|
|
if ($oldSeats > $newSeats) {
|
|
$license->load('licenseseats.user');
|
|
|
|
// Need to delete seats... lets see if if we have enough.
|
|
$seatsAvailableForDelete = $license->licenseseats->reject(function ($seat) {
|
|
return ((bool) $seat->assigned_to) || ((bool) $seat->asset_id);
|
|
});
|
|
|
|
if ($change > $seatsAvailableForDelete->count()) {
|
|
Session::flash('error', trans('admin/licenses/message.assoc_users'));
|
|
|
|
return false;
|
|
}
|
|
for ($i = 1; $i <= $change; $i++) {
|
|
$seatsAvailableForDelete->pop()->delete();
|
|
}
|
|
// Log Deletion of seats.
|
|
$logAction = new Actionlog;
|
|
$logAction->item_type = self::class;
|
|
$logAction->item_id = $license->id;
|
|
$logAction->user_id = Auth::id() ?: 1; // We don't have an id while running the importer from CLI.
|
|
$logAction->note = "deleted ${change} seats";
|
|
$logAction->target_id = null;
|
|
$logAction->logaction('delete seats');
|
|
|
|
return true;
|
|
}
|
|
// Else we're adding seats.
|
|
//Create enough seats for the change.
|
|
$licenseInsert = [];
|
|
for ($i = $oldSeats; $i < $newSeats; $i++) {
|
|
$licenseInsert[] = [
|
|
'user_id' => Auth::id(),
|
|
'license_id' => $license->id,
|
|
'created_at' => now(),
|
|
'updated_at' => now()
|
|
];
|
|
}
|
|
//Chunk and use DB transactions to prevent timeouts.
|
|
|
|
collect($licenseInsert)->chunk(1000)->each(function ($chunk) {
|
|
DB::transaction(function () use ($chunk) {
|
|
LicenseSeat::insert($chunk->toArray());
|
|
});
|
|
});
|
|
|
|
// On initial create, we shouldn't log the addition of seats.
|
|
if ($license->id) {
|
|
//Log the addition of license to the log.
|
|
$logAction = new Actionlog();
|
|
$logAction->item_type = self::class;
|
|
$logAction->item_id = $license->id;
|
|
$logAction->user_id = Auth::id() ?: 1; // Importer.
|
|
$logAction->note = "added ${change} seats";
|
|
$logAction->target_id = null;
|
|
$logAction->logaction('add seats');
|
|
}
|
|
|
|
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)
|
|
{
|
|
$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)
|
|
{
|
|
$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)
|
|
{
|
|
if ($value == '' || $value == '0000-00-00') {
|
|
$value = null;
|
|
} else {
|
|
$value = (new Carbon($value))->toDateString();
|
|
}
|
|
$this->attributes['expiration_date'] = $value;
|
|
}
|
|
|
|
/**
|
|
* Sets termination date attribute
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v2.0]
|
|
* @return mixed
|
|
*/
|
|
public function setTerminationDateAttribute($value)
|
|
{
|
|
if ($value == '' || $value == '0000-00-00') {
|
|
$value = null;
|
|
} else {
|
|
$value = (new Carbon($value))->toDateString();
|
|
}
|
|
$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()
|
|
{
|
|
return $this->belongsTo(\App\Models\Company::class, '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()
|
|
{
|
|
return $this->belongsTo(\App\Models\Category::class, '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()
|
|
{
|
|
return $this->belongsTo(\App\Models\Manufacturer::class, 'manufacturer_id');
|
|
}
|
|
|
|
/**
|
|
* Determine whether the user should be emailed on checkin/checkout
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v2.0]
|
|
* @return bool
|
|
*/
|
|
public function 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 bool
|
|
*/
|
|
public function requireAcceptance()
|
|
{
|
|
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()
|
|
{
|
|
|
|
if ($this->category->eula_text) {
|
|
return Helper::parseEscapedMarkedown($this->category->eula_text);
|
|
} elseif ($this->category->use_default_eula == '1') {
|
|
return Helper::parseEscapedMarkedown(Setting::getSettings()->default_eula_text);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Establishes the license -> assigned user relationship
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v2.0]
|
|
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
|
*/
|
|
public function assignedusers()
|
|
{
|
|
return $this->belongsToMany(\App\Models\User::class, 'license_seats', 'assigned_to', 'license_id');
|
|
}
|
|
|
|
/**
|
|
* Establishes the license -> action logs relationship
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v2.0]
|
|
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
|
*/
|
|
public function assetlog()
|
|
{
|
|
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
|
|
->where('item_type', '=', self::class)
|
|
->orderBy('created_at', 'desc');
|
|
}
|
|
|
|
/**
|
|
* 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()
|
|
{
|
|
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
|
|
->where('item_type', '=', self::class)
|
|
->where('action_type', '=', 'uploaded')
|
|
->whereNotNull('filename')
|
|
->orderBy('created_at', 'desc');
|
|
}
|
|
|
|
|
|
/**
|
|
* Establishes the license -> admin user relationship
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v2.0]
|
|
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
|
*/
|
|
public function adminuser()
|
|
{
|
|
return $this->belongsTo(\App\Models\User::class, 'user_id');
|
|
}
|
|
|
|
/**
|
|
* 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()
|
|
{
|
|
return LicenseSeat::whereNull('deleted_at')
|
|
->count();
|
|
}
|
|
|
|
|
|
/**
|
|
* 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()
|
|
{
|
|
return LicenseSeat::where('license_id', '=', $this->id)
|
|
->whereNull('deleted_at')
|
|
->count();
|
|
}
|
|
|
|
/**
|
|
* 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()
|
|
{
|
|
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()
|
|
{
|
|
if ($this->licenseSeatsRelation->first()) {
|
|
return $this->licenseSeatsRelation->first()->count;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* 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()
|
|
{
|
|
return LicenseSeat::whereNull('assigned_to')
|
|
->whereNull('asset_id')
|
|
->whereNull('deleted_at')
|
|
->count();
|
|
}
|
|
|
|
/**
|
|
* 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()
|
|
{
|
|
return $this->licenseSeatsRelation()
|
|
->whereNull('asset_id')
|
|
->whereNull('assigned_to')
|
|
->whereNull('deleted_at');
|
|
}
|
|
|
|
/**
|
|
* Sets the available seats attribute
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v3.0]
|
|
* @return mixed
|
|
*/
|
|
public function getAvailSeatsCountAttribute()
|
|
{
|
|
if ($this->availCount->first()) {
|
|
return $this->availCount->first()->count;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* 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()
|
|
{
|
|
return $this->licenseSeatsRelation()->where(function ($query) {
|
|
$query->whereNotNull('assigned_to')
|
|
->orWhereNotNull('asset_id');
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Sets the assigned seats attribute
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v1.0]
|
|
* @return int
|
|
*/
|
|
public function getAssignedSeatsCountAttribute()
|
|
{
|
|
if ($this->assignedCount->first()) {
|
|
return $this->assignedCount->first()->count;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Calculates the number of remaining seats
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v1.0]
|
|
* @return int
|
|
*/
|
|
public function remaincount()
|
|
{
|
|
$total = $this->licenseSeatsCount;
|
|
$taken = $this->assigned_seats_count;
|
|
$diff = ($total - $taken);
|
|
|
|
return $diff;
|
|
}
|
|
|
|
/**
|
|
* Returns the total number of seats for this license
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v1.0]
|
|
* @return int
|
|
*/
|
|
public function totalcount()
|
|
{
|
|
$avail = $this->availSeatsCount;
|
|
$taken = $this->assignedcount();
|
|
$diff = ($avail + $taken);
|
|
|
|
return $diff;
|
|
}
|
|
|
|
/**
|
|
* Establishes the license -> seats relationship
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v1.0]
|
|
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
|
*/
|
|
public function licenseseats()
|
|
{
|
|
return $this->hasMany(\App\Models\LicenseSeat::class);
|
|
}
|
|
|
|
/**
|
|
* Establishes the license -> supplier relationship
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v1.0]
|
|
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
|
*/
|
|
public function supplier()
|
|
{
|
|
return $this->belongsTo(\App\Models\Supplier::class, 'supplier_id');
|
|
}
|
|
|
|
|
|
/**
|
|
* Gets the next available free seat - used by
|
|
* the API to populate next_seat
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v3.0]
|
|
* @return mixed
|
|
*/
|
|
public function freeSeat()
|
|
{
|
|
return $this->licenseseats()
|
|
->whereNull('deleted_at')
|
|
->where(function ($query) {
|
|
$query->whereNull('assigned_to')
|
|
->whereNull('asset_id');
|
|
})
|
|
->orderBy('id', 'asc')
|
|
->first();
|
|
}
|
|
|
|
|
|
/**
|
|
* Establishes the license -> free seats relationship
|
|
*
|
|
* @author A. Gianotto <snipe@snipe.net>
|
|
* @since [v1.0]
|
|
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
|
*/
|
|
public function freeSeats()
|
|
{
|
|
return $this->hasMany(\App\Models\LicenseSeat::class)->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)
|
|
{
|
|
$days = (is_null($days)) ? 60 : $days;
|
|
|
|
return self::whereNotNull('expiration_date')
|
|
->whereNull('deleted_at')
|
|
->whereRaw(DB::raw('DATE_SUB(`expiration_date`,INTERVAL '.$days.' DAY) <= DATE(NOW()) '))
|
|
->where('expiration_date', '>', date('Y-m-d'))
|
|
->orderBy('expiration_date', 'ASC')
|
|
->get();
|
|
}
|
|
|
|
/**
|
|
* Query builder scope to order on manufacturer
|
|
*
|
|
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
|
* @param string $order Order
|
|
*
|
|
* @return \Illuminate\Database\Query\Builder Modified query builder
|
|
*/
|
|
public function scopeOrderManufacturer($query, $order)
|
|
{
|
|
return $query->leftJoin('manufacturers', 'licenses.manufacturer_id', '=', 'manufacturers.id')->select('licenses.*')
|
|
->orderBy('manufacturers.name', $order);
|
|
}
|
|
|
|
/**
|
|
* Query builder scope to order on supplier
|
|
*
|
|
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
|
* @param string $order Order
|
|
*
|
|
* @return \Illuminate\Database\Query\Builder Modified query builder
|
|
*/
|
|
public function scopeOrderSupplier($query, $order)
|
|
{
|
|
return $query->leftJoin('suppliers', 'licenses.supplier_id', '=', 'suppliers.id')->select('licenses.*')
|
|
->orderBy('suppliers.name', $order);
|
|
}
|
|
|
|
/**
|
|
* Query builder scope to order on company
|
|
*
|
|
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
|
* @param text $order Order
|
|
*
|
|
* @return \Illuminate\Database\Query\Builder Modified query builder
|
|
*/
|
|
public function scopeOrderCompany($query, $order)
|
|
{
|
|
return $query->leftJoin('companies as companies', 'licenses.company_id', '=', 'companies.id')->select('licenses.*')
|
|
->orderBy('companies.name', $order);
|
|
}
|
|
}
|