From 2a95a95e007f0366a1a25b569faeaa6e636dd96f Mon Sep 17 00:00:00 2001 From: Daniel Meltzer Date: Fri, 30 Sep 2016 00:20:49 -0500 Subject: [PATCH] Company to logs (#2717) * Fix the actionlog/companyables problem by adding a company_id to all actionlogs and scoping directly on that. Works around bugs in laravel where trying to hunt down the polymorphic relationship would lead to an infinite loop * Scope companyables in getactivityreport. Also eager load. * Improve reportscontroller, work on seeder to test this. * Only show company users in checkout dialogs * If no admin associated with log, it might be a request. Leave blank instead of saying deleted admin * When injecting company_id, use target instead of user if user is a superadmin * Build up the seeder to generate users, companies, and logs. * Eager load the log, don't scope the users log because the log should already include things only related to the user. --- app/Helpers/Helper.php | 2 +- app/Http/Controllers/AssetsController.php | 2 +- app/Http/Controllers/DashboardController.php | 8 +- app/Http/Controllers/ReportsController.php | 29 +++---- app/Http/Controllers/ViewAssetsController.php | 13 +++- app/Models/Actionlog.php | 20 +++-- app/Models/Company.php | 26 ++++++- database/factories/ModelFactory.php | 77 ++++++++++++++++++- .../2016_09_28_231359_add_company_to_logs.php | 44 +++++++++++ database/seeds/ActionlogSeeder.php | 6 +- database/seeds/CompanySeeder.php | 19 +++++ database/seeds/DatabaseSeeder.php | 4 +- database/seeds/UserSeeder.php | 18 +++++ 13 files changed, 231 insertions(+), 37 deletions(-) create mode 100644 database/migrations/2016_09_28_231359_add_company_to_logs.php create mode 100644 database/seeds/CompanySeeder.php create mode 100644 database/seeds/UserSeeder.php diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 91d3c3c78c..65d9e76957 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -204,7 +204,7 @@ class Helper public static function usersList() { $users_list = array( '' => trans('general.select_user')) + - User::where('deleted_at', '=', null) + Company::scopeCompanyables(User::where('deleted_at', '=', null)) ->where('show_in_list','=',1) ->orderBy('last_name', 'asc') ->orderBy('first_name', 'asc')->get() diff --git a/app/Http/Controllers/AssetsController.php b/app/Http/Controllers/AssetsController.php index 3c39477f58..d5e3e40f56 100755 --- a/app/Http/Controllers/AssetsController.php +++ b/app/Http/Controllers/AssetsController.php @@ -1156,7 +1156,7 @@ class AssetsController extends Controller 'target_id' => $item[$asset_tag][$batch_counter]['user_id'], 'target_type' => User::class, 'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'], - 'action_type' => 'checkout' + 'action_type' => 'checkout', ) ); diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 5cc95632b6..7142e6f003 100755 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -30,12 +30,6 @@ class DashboardController extends Controller // Show the page if (Auth::user()->hasAccess('admin')) { - $recent_activity = Actionlog::latest() - ->with('item') - ->take(20) - ->get(); - - $asset_stats['total'] = Asset::Hardware()->count(); $asset_stats['rtd']['total'] = Asset::Hardware()->RTD()->count(); @@ -82,7 +76,7 @@ class DashboardController extends Controller } - return View::make('dashboard')->with('asset_stats', $asset_stats)->with('recent_activity', $recent_activity); + return View::make('dashboard')->with('asset_stats', $asset_stats); } else { // Redirect to the profile page return redirect()->route('view-assets'); diff --git a/app/Http/Controllers/ReportsController.php b/app/Http/Controllers/ReportsController.php index 0e16bfdc79..a024b17042 100644 --- a/app/Http/Controllers/ReportsController.php +++ b/app/Http/Controllers/ReportsController.php @@ -308,7 +308,7 @@ class ReportsController extends Controller */ public function getActivityReportDataTable() { - $activitylogs = Actionlog::orderBy('created_at', 'DESC'); + $activitylogs = Company::scopeCompanyables(Actionlog::with('item', 'user', 'target'))->orderBy('created_at', 'DESC'); if (Input::has('search')) { $activity = $activity->TextSearch(e(Input::get('search'))); @@ -333,10 +333,10 @@ class ReportsController extends Controller $activityCount = $activitylogs->count(); - $activitylogs = $activitylogs->skip($offset)->take($limit)->get(); + // dd("Offset:" . $offset . " Limit " . $limit); + $activitylogs = $activitylogs->offset($offset)->limit($limit)->get(); $rows = array(); - foreach ($activitylogs as $activity) { if ($activity->itemType() == "asset") { @@ -354,24 +354,27 @@ class ReportsController extends Controller } if (($activity->item) && ($activity->itemType()=="asset")) { - $actvity_item = ''.e($activity->item->asset_tag).' - '. e($activity->item->showAssetName()).''; + $activity_item = ''.e($activity->item->asset_tag).' - '. e($activity->item->showAssetName()).''; $item_type = 'asset'; - } elseif ($activity->item) { - $actvity_item = ''.e($activity->item->name).''; + } elseif ($activity->item()) { + $activity_item = ''.e($activity->item->name).''; $item_type = $activity->itemType(); + } else { + $activity_item = "unkonwn"; + $item_type = "null"; } - if (($activity->userasassetlog) && ($activity->action_type=="uploaded") && ($activity->itemType()=="user")) { - $activity_target = ''.$activity->userasassetlog->fullName().''; - } elseif (($activity->item) && ($activity->target instanceof \App\Models\Asset)) { + if (($activity->user) && ($activity->action_type=="uploaded") && ($activity->itemType()=="user")) { + $activity_target = ''.$activity->user->fullName().''; + } elseif (($activity->item) && ($activity->target_type === "App\Models\Asset")) { $activity_target = ''.$activity->target->showAssetName().''; - } elseif (($activity->item) && ($activity->target instanceof \App\Models\User)) { + } elseif ( $activity->target_type === "App\Models\User") { $activity_target = ''.$activity->target->fullName().''; } elseif ($activity->action_type=='requested') { $activity_target = ''.$activity->user->fullName().''; } else { - $activity_target = $activity->target; + $activity_target = $activity->target->id; } @@ -379,9 +382,9 @@ class ReportsController extends Controller 'icon' => $activity_icons, 'created_at' => date("M d, Y g:iA", strtotime($activity->created_at)), 'action_type' => strtolower(trans('general.'.str_replace(' ','_',$activity->action_type))), - 'admin' => $activity->user ? (string) link_to('/admin/users/'.$activity->user_id.'/view', $activity->user->fullName()) : 'Deleted Admin', + 'admin' => $activity->user ? (string) link_to('/admin/users/'.$activity->user_id.'/view', $activity->user->fullName()) : '', 'target' => $activity_target, - 'item' => $actvity_item, + 'item' => $activity_item, 'item_type' => $item_type, 'note' => e($activity->note), diff --git a/app/Http/Controllers/ViewAssetsController.php b/app/Http/Controllers/ViewAssetsController.php index bc2401dbee..b4118fa786 100755 --- a/app/Http/Controllers/ViewAssetsController.php +++ b/app/Http/Controllers/ViewAssetsController.php @@ -39,7 +39,16 @@ class ViewAssetsController extends Controller public function getIndex() { - $user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find(Auth::user()->id); + $user = User::with( + 'assets', + 'assets.model', + 'consumables', + 'accessories', + 'licenses', + 'userloc', + 'userlog' + )->withTrashed()->find(Auth::user()->id); + $userlog = $user->userlog->load('item', 'user', 'target'); @@ -76,7 +85,7 @@ class ViewAssetsController extends Controller { $item = null; $fullItemType = 'App\\Models\\' . studly_case($itemType); - if($itemType == "asset_model") { + if ($itemType == "asset_model") { $itemType = "model"; } $item = call_user_func(array($fullItemType, 'find'), $itemId); diff --git a/app/Models/Actionlog.php b/app/Models/Actionlog.php index 37350ab7a8..316d2ff783 100755 --- a/app/Models/Actionlog.php +++ b/app/Models/Actionlog.php @@ -2,9 +2,10 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; -use Illuminate\Database\Eloquent\SoftDeletes; /** * Model for the Actionlog (the table that keeps a historical log of @@ -12,10 +13,9 @@ use Illuminate\Database\Eloquent\SoftDeletes; * * @version v1.0 */ -class Actionlog extends Model implements ICompanyableChild +class Actionlog extends Model { use SoftDeletes; - use CompanyableChildTrait; protected $dates = [ 'deleted_at' ]; @@ -23,11 +23,19 @@ class Actionlog extends Model implements ICompanyableChild public $timestamps = true; protected $fillable = [ 'created_at', 'item_type','user_id','item_id','action_type','note','target_id', 'target_type' ]; - public function getCompanyableParents() + // Overridden from Builder to automatically add the company + public static function boot() { - return [ 'accessorylog', 'assetlog', 'licenselog', 'consumablelog' ]; + parent::boot(); + static::creating( function (Actionlog $actionlog) { + // If the admin is a superadmin, let's see if the target instead has a company. + if (Auth::user() && Auth::user()->isSuperUser()) { + $actionlog->company_id = $actionlog->target->company_id; + } else if (Auth::user() && Auth::user()->company) { + $actionlog->company_id = Auth::user()->company_id; + } + }); } - // Eloquent Relationships below public function item() { diff --git a/app/Models/Company.php b/app/Models/Company.php index 28610767c9..f86a9a5320 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -136,7 +136,8 @@ final class Company extends Model public static function scopeCompanyables($query, $column = 'company_id') { - if (!static::isFullMultipleCompanySupportEnabled() || (Auth::check() && Auth::user()->isSuperUser())) { + // If not logged in and hitting this, assume we are on the command line and don't scope?' + if (!static::isFullMultipleCompanySupportEnabled() || (Auth::check() && Auth::user()->isSuperUser()) || (!Auth::check())) { return $query; } else { return static::scopeCompanyablesDirectly($query, $column); @@ -176,4 +177,27 @@ final class Company extends Model return e($company->name); } } + + public function users() { + return $this->hasMany(User::class); + } + + public function assets() { + return $this->hasMany(Asset::class); + } + + public function licenses() { + return $this->hasMany(License::class); + } + public function accessories() { + return $this->hasMany(Accessory::class); + } + + public function consumables() { + return $this->hasMany(Consumable::class); + } + + public function components() { + return $this->hasMany(Component::class); + } } diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index 82652aca86..b8acc76e8a 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -25,6 +25,7 @@ $factory->defineAs(App\Models\Asset::class, 'asset', function (Faker\Generator $ 'order_number' => $faker->numberBetween(1000000,50000000), 'supplier_id' => $faker->numberBetween(1,5), 'requestable' => $faker->numberBetween(0,1), + 'company_id' => \App\Models\Company::inRandomOrder()->first()->id ]; }); @@ -96,6 +97,7 @@ $factory->defineAs(App\Models\Component::class, 'component', function (Faker\Gen 'category_id' => $faker->numberBetween(21,25), 'total_qty' => $faker->numberBetween(3, 10), 'min_amt' => $faker->numberBetween($min = 1, $max = 2), + 'company_id' => \App\Models\Company::inRandomOrder()->first()->id ]; }); @@ -113,6 +115,7 @@ $factory->defineAs(App\Models\Accessory::class, 'accessory', function (Faker\Gen 'qty' => $faker->numberBetween(5, 10), 'location_id' => $faker->numberBetween(1,5), 'min_amt' => $faker->numberBetween($min = 1, $max = 2), + 'company_id' => \App\Models\Company::inRandomOrder()->first()->id ]; }); @@ -138,6 +141,7 @@ $factory->defineAs(App\Models\Consumable::class, 'consumable', function (Faker\G 'company_id' => $faker->numberBetween(1, 10), 'qty' => $faker->numberBetween(5, 10), 'min_amt' => $faker->numberBetween($min = 1, $max = 2), + 'company_id' => \App\Models\Company::inRandomOrder()->first()->id ]; }); @@ -251,6 +255,7 @@ $factory->defineAs(App\Models\License::class, 'license', function (Faker\Generat 'purchase_date' => $faker->dateTime(), 'purchase_cost' => $faker->randomFloat(2), 'notes' => $faker->sentence, + 'company_id' => \App\Models\Company::inRandomOrder()->first()->id ]; }); @@ -265,19 +270,82 @@ $factory->defineAs(App\Models\LicenseSeat::class, 'license-seat', function (Fake }); $factory->defineAs(App\Models\Actionlog::class, 'asset-checkout', function (Faker\Generator $faker) { + $company = \App\Models\Company::has('users')->has('assets')->inRandomOrder()->first(); return [ - 'user_id' => 1, + 'user_id' => $company->users()->inRandomOrder()->first()->id, 'action_type' => 'checkout', - 'item_id' => $faker->numberBetween(1, 10), - 'target_id' => 1, + 'item_id' => $company->assets()->inRandomOrder()->first()->id, + 'target_id' => $company->users()->inRandomOrder()->first()->id, 'target_type' => 'App\\Models\\User', 'created_at' => $faker->dateTime(), 'item_type' => 'App\\Models\\Asset', 'note' => $faker->sentence, - 'user_id' => '1', + 'company_id' => $company->id ]; }); +$factory->defineAs(App\Models\Actionlog::class, 'license-checkout-asset', function (Faker\Generator $faker) { + $company = \App\Models\Company::has('users')->has('licenses')->inRandomOrder()->first(); + + return [ + 'user_id' => $company->users()->inRandomOrder()->first()->id, + 'action_type' => 'checkout', + 'item_id' => $company->licenses()->whereNotNull('company_id')->inRandomOrder()->first()->id, + 'target_id' => $company->assets()->inRandomOrder()->first()->id, + 'target_type' => 'App\\Models\\Asset', + 'created_at' => $faker->dateTime(), + 'item_type' => 'App\\Models\\License', + 'note' => $faker->sentence, + 'company_id' => $company->id + ]; +}); + +$factory->defineAs(App\Models\Actionlog::class, 'accessory-checkout', function (Faker\Generator $faker) { + $company = \App\Models\Company::has('users')->has('accessories')->inRandomOrder()->first(); + return [ + 'user_id' => $company->users()->inRandomOrder()->first()->id, + 'action_type' => 'checkout', + 'item_id' => $company->accessories()->whereNotNull('company_id')->inRandomOrder()->first()->id, + 'target_id' => $company->users()->inRandomOrder()->first()->id, + 'target_type' => 'App\\Models\\User', + 'created_at' => $faker->dateTime(), + 'item_type' => 'App\\Models\\Accessory', + 'note' => $faker->sentence, + 'company_id' => $company->id + ]; +}); + +$factory->defineAs(App\Models\Actionlog::class, 'consumable-checkout', function (Faker\Generator $faker) { + $company = \App\Models\Company::has('users')->has('consumables')->inRandomOrder()->first(); + + return [ + 'user_id' => $company->users()->inRandomOrder()->first()->id, + 'action_type' => 'checkout', + 'item_id' => $company->consumables()->whereNotNull('company_id')->inRandomOrder()->first()->id, + 'target_id' => $company->users()->inRandomOrder()->first()->id, + 'target_type' => 'App\\Models\\User', + 'created_at' => $faker->dateTime(), + 'item_type' => 'App\\Models\\Consumable', + 'note' => $faker->sentence, + 'company_id' => $company->id + ]; +}); + +$factory->defineAs(App\Models\Actionlog::class, 'component-checkout', function (Faker\Generator $faker) { + $company = \App\Models\Company::has('users')->has('components')->inRandomOrder()->first(); + + return [ + 'user_id' => $company->users()->inRandomOrder()->first()->id, + 'action_type' => 'checkout', + 'item_id' => $company->components()->whereNotNull('company_id')->inRandomOrder()->first()->id, + 'target_id' => $company->users()->inRandomOrder()->first()->id, + 'target_type' => 'App\\Models\\User', + 'created_at' => $faker->dateTime(), + 'item_type' => 'App\\Models\\Component', + 'note' => $faker->sentence, + 'company_id' => $company->id + ]; +}); $factory->defineAs(App\Models\CustomField::class, 'customfield-ip', function (Faker\Generator $faker) { return [ @@ -295,5 +363,6 @@ $factory->defineAs(App\Models\User::class, 'valid-user', function (Faker\Generat 'email' => $faker->safeEmail, 'password' => $faker->password, 'username' => $faker->username, + 'company_id' => \App\Models\Company::inRandomOrder()->first()->id ]; }); diff --git a/database/migrations/2016_09_28_231359_add_company_to_logs.php b/database/migrations/2016_09_28_231359_add_company_to_logs.php new file mode 100644 index 0000000000..545c045d64 --- /dev/null +++ b/database/migrations/2016_09_28_231359_add_company_to_logs.php @@ -0,0 +1,44 @@ +integer('company_id')->nullable()->default(null); + }); + + $logs = Actionlog::with('item')->get(); + foreach ($logs as $log) { + if($log->item) { + $log->company_id = $log->item->company_id; + $log->save(); + } else { + var_dump($log); + } + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('action_logs', function (Blueprint $table) { + // + $table->dropColumn('company_id'); + }); + } +} diff --git a/database/seeds/ActionlogSeeder.php b/database/seeds/ActionlogSeeder.php index 1d01b438a1..f7f9dd4e0c 100644 --- a/database/seeds/ActionlogSeeder.php +++ b/database/seeds/ActionlogSeeder.php @@ -7,6 +7,10 @@ class ActionlogSeeder extends Seeder public function run() { Actionlog::truncate(); - factory(Actionlog::class, 'asset-checkout',5)->create(); + factory(Actionlog::class, 'asset-checkout',25)->create(); + factory(Actionlog::class, 'accessory-checkout',15)->create(); + factory(Actionlog::class, 'consumable-checkout', 15)->create(); + factory(Actionlog::class, 'component-checkout', 15)->create(); + factory(Actionlog::class, 'license-checkout-asset', 15)->create(); } } diff --git a/database/seeds/CompanySeeder.php b/database/seeds/CompanySeeder.php new file mode 100644 index 0000000000..5b8a238662 --- /dev/null +++ b/database/seeds/CompanySeeder.php @@ -0,0 +1,19 @@ +create(); + } +} diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index c6e094b5d1..b500b5f201 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -14,9 +14,12 @@ class DatabaseSeeder extends Seeder { Model::unguard(); + $this->call(CompanySeeder::class); + $this->call(UserSeeder::class); $this->call(AssetModelSeeder::class); $this->call(AccessorySeeder::class); $this->call(AssetSeeder::class); + $this->call(ComponentSeeder::class); $this->call(ConsumableSeeder::class); $this->call(StatuslabelSeeder::class); $this->call(SupplierSeeder::class); @@ -27,7 +30,6 @@ class DatabaseSeeder extends Seeder $this->call(ManufacturerSeeder::class); $this->call(LocationSeeder::class); $this->call(CustomFieldSeeder::class); - $this->call(ComponentSeeder::class); Model::reguard(); } diff --git a/database/seeds/UserSeeder.php b/database/seeds/UserSeeder.php new file mode 100644 index 0000000000..0141aab2cf --- /dev/null +++ b/database/seeds/UserSeeder.php @@ -0,0 +1,18 @@ +create(); + } +}