diff --git a/ansible/ubuntu/vagrant_playbook.yml b/ansible/ubuntu/vagrant_playbook.yml index dd25b2e0c2..44b1a6ef00 100755 --- a/ansible/ubuntu/vagrant_playbook.yml +++ b/ansible/ubuntu/vagrant_playbook.yml @@ -199,7 +199,7 @@ - { regexp: '^DB_PASSWORD=', line: 'DB_PASSWORD=vagrant' } - { regexp: '^APP_URL=', line: "APP_URL=http://{{ fqdn }}" } - { regexp: '^APP_ENV=', line: "APP_ENV=development" } - - { regexp: '^APP_DEBUG=', line: "APP_ENV=true" } + - { regexp: '^APP_DEBUG=', line: "APP_DEBUG=true" } - name: Generate application key shell: "php {{ app_path }}/artisan key:generate --force" - name: Artisan Migrate diff --git a/app/Http/Controllers/Api/ComponentsController.php b/app/Http/Controllers/Api/ComponentsController.php index d7af18b21c..cef8506d7b 100644 --- a/app/Http/Controllers/Api/ComponentsController.php +++ b/app/Http/Controllers/Api/ComponentsController.php @@ -8,6 +8,9 @@ use App\Http\Transformers\ComponentsTransformer; use App\Models\Company; use App\Models\Component; use Illuminate\Http\Request; +use App\Events\CheckoutableCheckedIn; +use App\Events\ComponentCheckedIn; +use App\Models\Asset; class ComponentsController extends Controller { @@ -172,4 +175,119 @@ class ComponentsController extends Controller $assets = $assets->skip($offset)->take($limit)->get(); return (new ComponentsTransformer)->transformCheckedoutComponents($assets, $total); } + + + /** + * Validate and checkout the component. + * + * @author [A. Gianotto] [] + * t + * @since [v5.1.8] + * @param Request $request + * @param int $componentId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function checkout(Request $request, $componentId) + { + // Check if the component exists + if (is_null($component = Component::find($componentId))) { + return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.does_not_exist'))); + } + + $this->authorize('checkout', $component); + + + if ($component->numRemaining() > $request->get('assigned_qty')) { + + if (!$asset = Asset::find($request->input('assigned_to'))) { + return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist'))); + } + + // Update the accessory data + $component->assigned_to = $request->input('assigned_to'); + + $component->assets()->attach($component->id, [ + 'component_id' => $component->id, + 'created_at' => \Carbon::now(), + 'assigned_qty' => $request->get('assigned_qty'), + 'user_id' => \Auth::id(), + 'asset_id' => $request->get('assigned_to') + ]); + + $component->logCheckout($request->input('note'), $asset); + + return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/components/message.checkout.success'))); + } + + return response()->json(Helper::formatStandardApiResponse('error', null, 'Not enough components remaining: '.$component->numRemaining().' remaining, '.$request->get('assigned_qty').' requested.')); + } + + /** + * Validate and store checkin data. + * + * @author [A. Gianotto] [] + * @since [v5.1.8] + * @param Request $request + * @param $component_asset_id + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function checkin(Request $request, $component_asset_id) + { + if ($component_assets = \DB::table('components_assets')->find($component_asset_id)) { + + if (is_null($component = Component::find($component_assets->component_id))) { + + return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.not_found'))); + } + + $this->authorize('checkin', $component); + + $max_to_checkin = $component_assets->assigned_qty; + + if ($max_to_checkin > 1) { + + $validator = \Validator::make($request->all(), [ + "checkin_qty" => "required|numeric|between:1,$max_to_checkin" + ]); + + if ($validator->fails()) { + return response()->json(Helper::formatStandardApiResponse('error', null, 'Checkin quantity must be between 1 and '.$max_to_checkin)); + } + } + + + // Validation passed, so let's figure out what we have to do here. + $qty_remaining_in_checkout = ($component_assets->assigned_qty - (int)$request->input('checkin_qty', 1)); + + // We have to modify the record to reflect the new qty that's + // actually checked out. + $component_assets->assigned_qty = $qty_remaining_in_checkout; + + \Log::debug($component_asset_id.' - '.$qty_remaining_in_checkout.' remaining in record '.$component_assets->id); + + \DB::table('components_assets')->where('id', + $component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]); + + // If the checked-in qty is exactly the same as the assigned_qty, + // we can simply delete the associated components_assets record + if ($qty_remaining_in_checkout == 0) { + \DB::table('components_assets')->where('id', '=', $component_asset_id)->delete(); + } + + + $asset = Asset::find($component_assets->asset_id); + + event(new CheckoutableCheckedIn($component, $asset, \Auth::user(), $request->input('note'), \Carbon::now())); + + return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/components/message.checkin.success'))); + + } + + return response()->json(Helper::formatStandardApiResponse('error', null, 'No matching checkouts for that component join record')); + + + } + } diff --git a/public/js/build/app.js b/public/js/build/app.js index 128d7a0037..6ce1b4d451 100644 Binary files a/public/js/build/app.js and b/public/js/build/app.js differ diff --git a/public/js/dist/all.js b/public/js/dist/all.js index fbaf0ed4c3..c4d64f0393 100644 Binary files a/public/js/dist/all.js and b/public/js/dist/all.js differ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 777b48f757..5725c1cfbe 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -1,24 +1,24 @@ { - "/js/build/app.js": "/js/build/app.js?id=a6211ef5d716a9723660", - "/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=d4b206b68326a81a37aa", - "/css/build/app.css": "/css/build/app.css?id=2da4f8fd0e80c4232b92", - "/css/build/overrides.css": "/css/build/overrides.css?id=0bb9f67c5f027502f7da", - "/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=dea194b1336f156866c2", - "/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=b9d1005a03a7e60c138e", - "/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=ac15efa2e742bc1e8a6b", - "/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=e4c4239c8468412ab44d", - "/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=f193c19123720dca0e39", - "/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=ee7618c270b8a9b0f306", - "/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=a147d49ecaa5ede9b82e", - "/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=4b9b84247ac2b0798b14", - "/css/dist/skins/skin-purple.css": "/css/dist/skins/skin-purple.css?id=ed339802f92e98ee5a1b", - "/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=9dafcf0920f2681450f6", - "/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=2b89bd74fcf3846791f5", - "/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=9e8cfd430e8a4cecff36", - "/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=ad1ac8316e93597f9191", - "/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=ddd1c21e2cfdaf500ef5", - "/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=279fd3bd5a093698c223", - "/css/dist/all.css": "/css/dist/all.css?id=53f8c26d43ca1bea78b0", + "/js/build/app.js": "/js/build/app.js?id=a8c00cafc45d790258ff", + "/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=89f2b7816c4e00784b59", + "/css/build/app.css": "/css/build/app.css?id=f534465acd801cafe2a2", + "/css/build/overrides.css": "/css/build/overrides.css?id=c544472168a356889508", + "/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=2da78d31ca46509e2927", + "/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=0845c3960331dcd5db3c", + "/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=83a9d7106a863eb4536d", + "/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=1f137fd2dcbac676d291", + "/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=2528e832e4cc3e8c8e07", + "/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=5ef650950378aeb72dfa", + "/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=92e03e5789f89a01c8de", + "/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=88e8f7eb001cb99015e9", + "/css/dist/skins/skin-purple.css": "/css/dist/skins/skin-purple.css?id=bbbca0f0b0b6c6a5e6a5", + "/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=0f6ee46fdfebc51f842a", + "/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=99b98cccd8992e8d9ee2", + "/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=063db6b6f925af639845", + "/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=74c833507f423fb041c2", + "/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=e4a8920935dc11ca5cd2", + "/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=96477616f4a4b4ff1db8", + "/css/dist/all.css": "/css/dist/all.css?id=cc906fab5ad666abe433", "/css/blue.png": "/css/blue.png?id=e83a6c29e04fe851f212", "/css/blue@2x.png": "/css/blue@2x.png?id=51135dd4d24f88f5de0b", "/css/dist/signature-pad.css": "/css/dist/signature-pad.css?id=6a89d3cd901305e66ced", @@ -26,20 +26,20 @@ "/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=d729a1e2e97f290cc4e2", "/js/build/vendor.js": "/js/build/vendor.js?id=b93877b4a88a76e1b18b", "/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=a17945119a381c758e1f", - "/js/dist/all.js": "/js/dist/all.js?id=a3c6e35d8ad8e1bef4e4", - "/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=e4c4239c8468412ab44d", - "/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=f193c19123720dca0e39", - "/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=ee7618c270b8a9b0f306", - "/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=a147d49ecaa5ede9b82e", - "/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=dea194b1336f156866c2", - "/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=ad1ac8316e93597f9191", - "/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=2b89bd74fcf3846791f5", - "/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=9e8cfd430e8a4cecff36", - "/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=b9d1005a03a7e60c138e", - "/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=4b9b84247ac2b0798b14", - "/css/dist/skins/skin-purple.min.css": "/css/dist/skins/skin-purple.min.css?id=ed339802f92e98ee5a1b", - "/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=9dafcf0920f2681450f6", - "/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=279fd3bd5a093698c223", - "/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=ddd1c21e2cfdaf500ef5", - "/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=ac15efa2e742bc1e8a6b" + "/js/dist/all.js": "/js/dist/all.js?id=38dfc3d80da2a5dda2e5", + "/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=1f137fd2dcbac676d291", + "/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=2528e832e4cc3e8c8e07", + "/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=5ef650950378aeb72dfa", + "/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=92e03e5789f89a01c8de", + "/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=2da78d31ca46509e2927", + "/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=74c833507f423fb041c2", + "/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=99b98cccd8992e8d9ee2", + "/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=063db6b6f925af639845", + "/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=0845c3960331dcd5db3c", + "/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=88e8f7eb001cb99015e9", + "/css/dist/skins/skin-purple.min.css": "/css/dist/skins/skin-purple.min.css?id=bbbca0f0b0b6c6a5e6a5", + "/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=0f6ee46fdfebc51f842a", + "/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=96477616f4a4b4ff1db8", + "/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=e4a8920935dc11ca5cd2", + "/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=83a9d7106a863eb4536d" } diff --git a/resources/assets/js/vue.js b/resources/assets/js/vue.js index f55ef15c43..b31792d089 100644 --- a/resources/assets/js/vue.js +++ b/resources/assets/js/vue.js @@ -13,27 +13,27 @@ require('./bootstrap'); */ Vue.component( 'passport-clients', - require('./components/passport/Clients.vue') + require('./components/passport/Clients.vue').default ); Vue.component( 'passport-authorized-clients', - require('./components/passport/AuthorizedClients.vue') + require('./components/passport/AuthorizedClients.vue').default ); Vue.component( 'passport-personal-access-tokens', - require('./components/passport/PersonalAccessTokens.vue') + require('./components/passport/PersonalAccessTokens.vue').default ); Vue.component( 'importer', - require('./components/importer/importer.vue') + require('./components/importer/importer.vue').default ); Vue.component( 'fieldset-default-values', - require('./components/forms/asset-models/fieldset-default-values.vue') + require('./components/forms/asset-models/fieldset-default-values.vue').default ); // Commented out currently to avoid trying to load vue everywhere. diff --git a/routes/api.php b/routes/api.php index c8f05d2f19..51bd4614d6 100644 --- a/routes/api.php +++ b/routes/api.php @@ -159,7 +159,7 @@ Route::group(['prefix' => 'v1','namespace' => 'Api', 'middleware' => 'auth:api'] 'destroy' => 'api.companies.destroy' ], 'except' => ['create', 'edit'], - 'parameters' => ['component' => 'component_id'] + 'parameters' => ['company' => 'company_id'] ] ); // Companies resource @@ -220,6 +220,21 @@ Route::group(['prefix' => 'v1','namespace' => 'Api', 'middleware' => 'auth:api'] 'uses' => 'ComponentsController@getAssets', ] ); + + Route::post('{component}/checkout', + [ + 'as' =>'api.components.checkout', + 'uses' => 'ComponentsController@checkout', + ] + ); + + Route::post('{component}/checkin', + [ + 'as' =>'api.components.checkin', + 'uses' => 'ComponentsController@checkin', + ] + ); + }); // Components group