diff --git a/app/Http/Controllers/Api/AccessoriesController.php b/app/Http/Controllers/Api/AccessoriesController.php index 6ef76a5d93..08a39749f5 100644 --- a/app/Http/Controllers/Api/AccessoriesController.php +++ b/app/Http/Controllers/Api/AccessoriesController.php @@ -8,6 +8,7 @@ use App\Helpers\Helper; use App\Models\Accessory; use App\Http\Transformers\AccessoriesTransformer; use App\Models\Company; +use App\Http\Transformers\SelectlistTransformer; class AccessoriesController extends Controller @@ -201,4 +202,28 @@ class AccessoriesController extends Controller return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.delete.success'))); } + + /** + * Gets a paginated collection for the select2 menus + * + * @see \App\Http\Transformers\SelectlistTransformer + * + */ + public function selectlist(Request $request) + { + + $accessories = Accessory::select([ + 'accessories.id', + 'accessories.name' + ]); + + if ($request->filled('search')) { + $accessories = $accessories->where('accessories.name', 'LIKE', '%'.$request->get('search').'%'); + } + + $accessories = $accessories->orderBy('name', 'ASC')->paginate(50); + + + return (new SelectlistTransformer)->transformSelectlist($accessories); + } } diff --git a/app/Http/Controllers/Api/ConsumablesController.php b/app/Http/Controllers/Api/ConsumablesController.php index be2b07437d..f5dc8c8dee 100644 --- a/app/Http/Controllers/Api/ConsumablesController.php +++ b/app/Http/Controllers/Api/ConsumablesController.php @@ -8,6 +8,7 @@ use App\Models\Company; use App\Models\Consumable; use App\Http\Transformers\ConsumablesTransformer; use App\Helpers\Helper; +use App\Http\Transformers\SelectlistTransformer; class ConsumablesController extends Controller { @@ -191,4 +192,28 @@ class ConsumablesController extends Controller $data = array('total' => $consumableCount, 'rows' => $rows); return $data; } + + /** + * Gets a paginated collection for the select2 menus + * + * @see \App\Http\Transformers\SelectlistTransformer + * + */ + public function selectlist(Request $request) + { + + $consumables = Consumable::select([ + 'consumables.id', + 'consumables.name' + ]); + + if ($request->filled('search')) { + $consumables = $consumables->where('consumables.name', 'LIKE', '%'.$request->get('search').'%'); + } + + $consumables = $consumables->orderBy('name', 'ASC')->paginate(50); + + + return (new SelectlistTransformer)->transformSelectlist($consumables); + } } diff --git a/app/Http/Controllers/Api/LicensesController.php b/app/Http/Controllers/Api/LicensesController.php index c8ead62b86..089f9ce85a 100644 --- a/app/Http/Controllers/Api/LicensesController.php +++ b/app/Http/Controllers/Api/LicensesController.php @@ -11,6 +11,7 @@ use App\Models\License; use App\Models\LicenseSeat; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; +use App\Http\Transformers\SelectlistTransformer; class LicensesController extends Controller { @@ -253,5 +254,29 @@ class LicensesController extends Controller } + + /** + * Gets a paginated collection for the select2 menus + * + * @see \App\Http\Transformers\SelectlistTransformer + */ + public function selectlist(Request $request) + { + + $licenses = License::select([ + 'licenses.id', + 'licenses.name' + ]); + + if ($request->filled('search')) { + $licenses = $licenses->where('licenses.name', 'LIKE', '%'.$request->get('search').'%'); + } + + $licenses = $licenses->orderBy('name', 'ASC')->paginate(50); + + + return (new SelectlistTransformer)->transformSelectlist($licenses); + } + } diff --git a/app/Http/Controllers/Api/PredefinedKitsController.php b/app/Http/Controllers/Api/PredefinedKitsController.php new file mode 100644 index 0000000000..6cf0f7bca1 --- /dev/null +++ b/app/Http/Controllers/Api/PredefinedKitsController.php @@ -0,0 +1,449 @@ +] + */ +class PredefinedKitsController extends Controller +{ + /** + * Display a listing of the resource. + * + * @return \Illuminate\Http\Response + */ + public function index(Request $request) + { + $this->authorize('view', PredefinedKit::class); + $allowed_columns = ['id', 'name']; + + $kits = PredefinedKit::query(); + + if ($request->filled('search')) { + $kits = $kits->TextSearch($request->input('search')); + } + + $offset = $request->input('offset', 0); + $limit = $request->input('limit', 50); + $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count'; + $kits->orderBy($sort, $order); + + $total = $kits->count(); + $kits = $kits->skip($offset)->take($limit)->get(); + return (new PredefinedKitsTransformer)->transformPredefinedKits($kits, $total); + + } + + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + $this->authorize('create', PredefinedKit::class); + $kit = new PredefinedKit; + $kit->fill($request->all()); + + if ($kit->save()) { + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Created was successfull')); // TODO: trans + } + return response()->json(Helper::formatStandardApiResponse('error', null, $kit->getErrors())); + + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function show($id) + { + $this->authorize('view', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($id); + return (new PredefinedKitsTransformer)->transformPredefinedKit($kit); + } + + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id kit id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { + $this->authorize('update', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($id); + $kit->fill($request->all()); + + if ($kit->save()) { + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Update was successfull')); // TODO: trans + } + + return response()->json(Helper::formatStandardApiResponse('error', null, $kit->getErrors())); + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy($id) + { + $this->authorize('delete', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($id); + + // Delete childs + $kit->models()->detach(); + $kit->licenses()->detach(); + $kit->consumables()->detach(); + $kit->accessories()->detach(); + + $kit->delete(); + return response()->json(Helper::formatStandardApiResponse('success', null, 'Delete was successfull')); // TODO: trans + + } + + + /** + * Gets a paginated collection for the select2 menus + * + * @see \App\Http\Transformers\SelectlistTransformer + * + */ + public function selectlist(Request $request) + { + + $kits = PredefinedKit::select([ + 'id', + 'name' + ]); + + if ($request->filled('search')) { + $kits = $kits->where('name', 'LIKE', '%'.$request->get('search').'%'); + } + + $kits = $kits->orderBy('name', 'ASC')->paginate(50); + + return (new SelectlistTransformer)->transformSelectlist($kits); + + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function indexLicenses($kit_id) { + $this->authorize('view', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + $licenses = $kit->licenses; + return (new PredefinedKitsTransformer)->transformElements($licenses, $licenses->count()); + } + + + /** + * Store the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function storeLicense(Request $request, $kit_id) + { + $this->authorize('update', PredefinedKit::class); + + $kit = PredefinedKit::findOrFail($kit_id); + $quantity = $request->input('quantity', 1); + if( $quantity < 1) { + $quantity = 1; + } + + $license_id = $request->get('license'); + $relation = $kit->licenses(); + if( $relation->find($license_id) ) { + return response()->json(Helper::formatStandardApiResponse('error', null, ['license' => 'License already attached to kit'])); + } + + $relation->attach( $license_id, ['quantity' => $quantity]); + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'License added successfull')); // TODO: trans + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function updateLicense(Request $request, $kit_id, $license_id) + { + $this->authorize('update', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + $quantity = $request->input('quantity', 1); + if( $quantity < 1) { + $quantity = 1; + } + $kit->licenses()->syncWithoutDetaching([$license_id => ['quantity' => $quantity]]); + + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'License updated')); // TODO: trans + } + + /** + * Remove the specified resource from storage. + * + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function detachLicense($kit_id, $license_id) + { + $this->authorize('update', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + + $kit->licenses()->detach($license_id); + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Delete was successfull')); // TODO: trans + } + + /** + * Display the specified resource. + * + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function indexModels($kit_id) { + $this->authorize('view', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + $models = $kit->models; + return (new PredefinedKitsTransformer)->transformElements($models, $models->count()); + } + + /** + * Store the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function storeModel(Request $request, $kit_id) + { + //return response()->json(Helper::formatStandardApiResponse('error', 'string11', dd($request))); // TODO: trans + + $this->authorize('update', PredefinedKit::class); + + $kit = PredefinedKit::findOrFail($kit_id); + + $model_id = $request->get('model'); + $quantity = $request->input('quantity', 1); + if( $quantity < 1) { + $quantity = 1; + } + + $relation = $kit->models(); + if( $relation->find($model_id) ) { + return response()->json(Helper::formatStandardApiResponse('error', null, ['model' => 'Model already attached to kit'])); + } + $relation->attach($model_id, ['quantity' => $quantity]); + + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Model added successfull')); // TODO: trans + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function updateModel(Request $request, $kit_id, $model_id) + { + $this->authorize('update', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + $quantity = $request->input('quantity', 1); + if( $quantity < 1) { + $quantity = 1; + } + $kit->models()->syncWithoutDetaching([$model_id => ['quantity' => $quantity]]); + + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'License updated')); // TODO: trans + } + + /** + * Remove the specified resource from storage. + * + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function detachModel($kit_id, $model_id) + { + $this->authorize('update', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + + $kit->models()->detach($model_id); + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Delete was successfull')); // TODO: trans + } + + + + /** + * Display the specified resource. + * + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function indexConsumables($kit_id) { + $this->authorize('view', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + $consumables = $kit->consumables; + return (new PredefinedKitsTransformer)->transformElements($consumables, $consumables->count()); + } + + + /** + * Store the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function storeConsumable(Request $request, $kit_id) + { + $this->authorize('update', PredefinedKit::class); + + $kit = PredefinedKit::findOrFail($kit_id); + $quantity = $request->input('quantity', 1); + if( $quantity < 1) { + $quantity = 1; + } + + $consumable_id = $request->get('consumable'); + $relation = $kit->consumables(); + if( $relation->find($consumable_id) ) { + return response()->json(Helper::formatStandardApiResponse('error', null, ['consumable' => 'Consumable already attached to kit'])); + } + + $relation->attach( $consumable_id, ['quantity' => $quantity]); + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Consumable added successfull')); // TODO: trans + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function updateConsumable(Request $request, $kit_id, $consumable_id) + { + $this->authorize('update', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + $quantity = $request->input('quantity', 1); + if( $quantity < 1) { + $quantity = 1; + } + $kit->consumables()->syncWithoutDetaching([$consumable_id => ['quantity' => $quantity]]); + + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Consumable updated')); // TODO: trans + } + + /** + * Remove the specified resource from storage. + * + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function detachConsumable($kit_id, $consumable_id) + { + $this->authorize('update', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + + $kit->consumables()->detach($consumable_id); + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Delete was successfull')); // TODO: trans + } + + + /** + * Display the specified resource. + * + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function indexAccessories($kit_id) { + $this->authorize('view', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + $accessories = $kit->accessories; + return (new PredefinedKitsTransformer)->transformElements($accessories, $accessories->count()); + } + + + /** + * Store the specified resource. + * + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function storeAccessory(Request $request, $kit_id) + { + $this->authorize('update', PredefinedKit::class); + + $kit = PredefinedKit::findOrFail($kit_id); + $quantity = $request->input('quantity', 1); + if( $quantity < 1) { + $quantity = 1; + } + + $accessory_id = $request->get('accessory'); + $relation = $kit->accessories(); + if( $relation->find($accessory_id) ) { + return response()->json(Helper::formatStandardApiResponse('error', null, ['accessory' => 'Accessory already attached to kit'])); + } + + $relation->attach( $accessory_id, ['quantity' => $quantity]); + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Accessory added successfull')); // TODO: trans + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function updateAccessory(Request $request, $kit_id, $accessory_id) + { + $this->authorize('update', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + $quantity = $request->input('quantity', 1); + if( $quantity < 1) { + $quantity = 1; + } + $kit->accessories()->syncWithoutDetaching([$accessory_id => ['quantity' => $quantity]]); + + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Accessory updated')); // TODO: trans + } + + /** + * Remove the specified resource from storage. + * + * @param int $kit_id + * @return \Illuminate\Http\Response + */ + public function detachAccessory($kit_id, $accessory_id) + { + $this->authorize('update', PredefinedKit::class); + $kit = PredefinedKit::findOrFail($kit_id); + + $kit->accessories()->detach($accessory_id); + return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Delete was successfull')); // TODO: trans + } +} diff --git a/app/Http/Controllers/Kits/CheckoutKitController.php b/app/Http/Controllers/Kits/CheckoutKitController.php new file mode 100644 index 0000000000..0007372a46 --- /dev/null +++ b/app/Http/Controllers/Kits/CheckoutKitController.php @@ -0,0 +1,75 @@ +] + */ +class CheckoutKitController extends Controller +{ + + public $kitService; + use CheckInOutRequest; + + public function __construct(PredefinedKitCheckoutService $kitService) + { + $this->kitService = $kitService; + } + + /** + * Show Bulk Checkout Page + * + * @author [D. Minaev.] [] + * @return View View to checkout + */ + public function showCheckout($kit_id) + { + $this->authorize('checkout', Asset::class); + + $kit = PredefinedKit::findOrFail($kit_id); + return view('kits/checkout')->with('kit', $kit); + } + + /** + * Validate and process the new Predefined Kit data. + * + * @author [D. Minaev.] [] + * @return Redirect + */ + public function store(Request $request, $kit_id) + { + $user_id = e($request->get('user_id')); + if (is_null($user = User::find($user_id))) { + return redirect()->back()->with('error', trans('admin/users/message.user_not_found')); + } + + $kit = new PredefinedKit(); + $kit->id = $kit_id; + + $errors = $this->kitService->checkout($request, $kit, $user); + if (count($errors) > 0) { + return redirect()->back()->with('error', 'Checkout error')->with('error_messages', $errors); // TODO: trans + } + return redirect()->back()->with('success', 'Checkout was successfully'); // TODO: trans + + } +} diff --git a/app/Http/Controllers/Kits/PredefinedKitsController.php b/app/Http/Controllers/Kits/PredefinedKitsController.php new file mode 100644 index 0000000000..2ae5ca0111 --- /dev/null +++ b/app/Http/Controllers/Kits/PredefinedKitsController.php @@ -0,0 +1,474 @@ +] + */ +class PredefinedKitsController extends Controller +{ + /** + * @author [D. Minaev] [] + * @return \Illuminate\Contracts\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function index() + { + $this->authorize('index', PredefinedKit::class); + return view('kits/index'); + } + + /** + * Returns a form view to create a new kit. + * + * @author [D. Minaev] [] + * @throws \Illuminate\Auth\Access\AuthorizationException + * @return mixed + */ + public function create() + { + $this->authorize('create', PredefinedKit::class); + return view('kits/create')->with('item', new PredefinedKit); + } + + /** + * Validate and process the new Predefined Kit data. + * + * @author [D. Minaev] [] + * @return Redirect + */ + public function store(ImageUploadRequest $request) + { + $this->authorize('create', PredefinedKit::class); + // Create a new Predefined Kit + $kit = new PredefinedKit; + $kit->name = $request->input('name'); + + if (!$kit->save()) { + return redirect()->back()->withInput()->withErrors($kit->getErrors()); + } + $success = $kit->save(); + if (!$success) { + return redirect()->back()->withInput()->withErrors($kit->getErrors()); + } + return redirect()->route("kits.index")->with('success', 'Kit was successfully created.'); // TODO: trans() + } + + /** + * Returns a view containing the Predefined Kit edit form. + * + * @author [D. Minaev] [] + * @since [v1.0] + * @param int $kit_id + * @return View + */ + public function edit($kit_id=null) + { + $this->authorize('update', PredefinedKit::class); + if ($kit = PredefinedKit::find($kit_id)) { + return view('kits/edit') + ->with('item', $kit) + ->with('models', $kit->models) + ->with('licenses', $kit->licenses); + } + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + + /** + * Validates and processes form data from the edit + * Predefined Kit form based on the kit ID passed. + * + * @author [D. Minaev] [] + * @since [v1.0] + * @param int $kit_id + * @return Redirect + */ + public function update(ImageUploadRequest $request, $kit_id=null) + { + $this->authorize('update', PredefinedKit::class); + // Check if the kit exists + if (is_null($kit = PredefinedKit::find($kit_id))) { + // Redirect to the kits management page + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + $kit->name = $request->input('name'); + + if ($kit->save()) { + return redirect()->route("kits.index")->with('success', 'Kit was successfully updated'); // TODO: trans + } + return redirect()->back()->withInput()->withErrors($kit->getErrors()); + } + + /** + * Validate and delete the given Predefined Kit. + * Also delete all contained helping items + * + * @author [D. Minaev] [] + * @since [v1.0] + * @param int $kit_id + * @return Redirect + */ + public function destroy($kit_id) + { + $this->authorize('delete', PredefinedKit::class); + // Check if the kit exists + if (is_null($kit = PredefinedKit::find($kit_id))) { + return redirect()->route('kits.index')->with('error', 'Kit not found'); // TODO: trans + } + + // Delete childs + $kit->models()->detach(); + $kit->licenses()->detach(); + $kit->consumables()->detach(); + $kit->accessories()->detach(); + // Delete the kit + $kit->delete(); + + // Redirect to the kit management page + return redirect()->route('kits.index')->with('success', 'Kit was successfully deleted'); // TODO: trans + } + + /** + * Get the kit information to present to the kit view page + * + * @author [D. Minaev] [] + * @since [v1.0] + * @param int $modelId + * @return View + */ + public function show($kit_id=null) + { + return $this->edit($kit_id); + } + + + /** + * Returns a view containing the Predefined Kit edit form. + * + * @author [D. Minaev] [] + * @param int $kit_id + * @return View + */ + public function editModel($kit_id, $model_id) + { + $this->authorize('update', PredefinedKit::class); + if (($kit = PredefinedKit::find($kit_id)) + && ($model = $kit->models()->find($model_id))) { + + return view('kits/model-edit', [ + 'kit' => $kit, + 'model' => $model, + 'item' => $model->pivot + ]); + } + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + /** + * Get the kit information to present to the kit view page + * + * @author [D. Minaev] [] + * @param int $modelId + * @return View + */ + public function updateModel(Request $request, $kit_id, $model_id) + { + + $this->authorize('update', PredefinedKit::class); + if (is_null($kit = PredefinedKit::find($kit_id))) { + // Redirect to the kits management page + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + $validator = \Validator::make($request->all(), $kit->makeModelRules($model_id)); + + if ($validator->fails()) { + return redirect()->back()->withInput()->withErrors($validator); + } + + $pivot = $kit->models()->wherePivot('id', $request->input('pivot_id'))->first()->pivot; + + $pivot->model_id = $request->input('model_id'); + $pivot->quantity = $request->input('quantity'); + $pivot->save(); + + return redirect()->route('kits.edit', $kit_id)->with('success', 'Model updated successfully.'); // TODO: trans + } + + /** + * Remove the model from set + * + * @author [D. Minaev] [] + * @param int $modelId + * @return View + */ + public function detachModel($kit_id, $model_id) + { + $this->authorize('update', PredefinedKit::class); + if (is_null($kit = PredefinedKit::find($kit_id))) { + // Redirect to the kits management page + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + // Delete childs + $kit->models()->detach($model_id); + + // Redirect to the kit management page + return redirect()->route('kits.edit', $kit_id)->with('success', 'Model was successfully detached'); // TODO: trans + } + + /** + * Returns a view containing attached license edit form. + * + * @author [D. Minaev] [] + * @param int $kit_id + * @param int $license_id + * @return View + */ + public function editLicense($kit_id, $license_id) + { + $this->authorize('update', PredefinedKit::class); + if (!($kit = PredefinedKit::find($kit_id))) { + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + if (!($license = $kit->licenses()->find($license_id))) { + return redirect()->route('kits.index')->with('error', 'License does not exist'); // TODO: trans + } + + return view('kits/license-edit', [ + 'kit' => $kit, + 'license' => $license, + 'item' => $license->pivot + ]); + } + + /** + * Update attached licese + * + * @author [D. Minaev] [] + * @param int $kit_id + * @param int $license_id + * @return View + */ + public function updateLicense(Request $request, $kit_id, $license_id) + { + + $this->authorize('update', PredefinedKit::class); + if (is_null($kit = PredefinedKit::find($kit_id))) { + // Redirect to the kits management page + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + $validator = \Validator::make($request->all(), $kit->makeLicenseRules($license_id)); + + if ($validator->fails()) { + return redirect()->back()->withInput()->withErrors($validator); + } + + $pivot = $kit->licenses()->wherePivot('id', $request->input('pivot_id'))->first()->pivot; + + $pivot->license_id = $request->input('license_id'); + $pivot->quantity = $request->input('quantity'); + $pivot->save(); + + return redirect()->route('kits.edit', $kit_id)->with('success', 'License updated successfully.'); // TODO: trans + } + + /** + * Remove the license from set + * + * @author [D. Minaev] [] + * @param int $kit_id + * @param int $license_id + * @return View + */ + public function detachLicense($kit_id, $license_id) + { + $this->authorize('update', PredefinedKit::class); + if (is_null($kit = PredefinedKit::find($kit_id))) { + // Redirect to the kits management page + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + // Delete childs + $kit->licenses()->detach($license_id); + + // Redirect to the kit management page + return redirect()->route('kits.edit', $kit_id)->with('success', 'License was successfully detached'); // TODO: trans + } + + + /** + * Returns a view containing attached accessory edit form. + * + * @author [D. Minaev] [] + * @param int $kit_id + * @param int $accessoryId + * @return View + */ + public function editAccessory($kit_id, $accessory_id) + { + $this->authorize('update', PredefinedKit::class); + if (!($kit = PredefinedKit::find($kit_id))) { + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + if (!($accessory = $kit->accessories()->find($accessory_id))) { + return redirect()->route('kits.index')->with('error', 'Accessory does not exist'); // TODO: trans + } + + return view('kits/accessory-edit', [ + 'kit' => $kit, + 'accessory' => $accessory, + 'item' => $accessory->pivot + ]); + } + + /** + * Update attached accessory + * + * @author [D. Minaev] [] + * @param int $kit_id + * @param int $accessory_id + * @return View + */ + public function updateAccessory(Request $request, $kit_id, $accessory_id) + { + + $this->authorize('update', PredefinedKit::class); + if (is_null($kit = PredefinedKit::find($kit_id))) { + // Redirect to the kits management page + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + $validator = \Validator::make($request->all(), $kit->makeAccessoryRules($accessory_id)); + + if ($validator->fails()) { + return redirect()->back()->withInput()->withErrors($validator); + } + + $pivot = $kit->accessories()->wherePivot('id', $request->input('pivot_id'))->first()->pivot; + + $pivot->accessory_id = $request->input('accessory_id'); + $pivot->quantity = $request->input('quantity'); + $pivot->save(); + + return redirect()->route('kits.edit', $kit_id)->with('success', 'Accessory updated successfully.'); // TODO: trans + } + + /** + * Remove the accessory from set + * + * @author [D. Minaev] [] + * @param int $accessory_id + * @return View + */ + public function detachAccessory($kit_id, $accessory_id) + { + $this->authorize('update', PredefinedKit::class); + if (is_null($kit = PredefinedKit::find($kit_id))) { + // Redirect to the kits management page + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + // Delete childs + $kit->accessories()->detach($accessory_id); + + // Redirect to the kit management page + return redirect()->route('kits.edit', $kit_id)->with('success', 'Accessory was successfully detached'); // TODO: trans + } + + /** + * Returns a view containing attached consumable edit form. + * + * @author [D. Minaev] [] + * @param int $kit_id + * @param int $consumable_id + * @return View + */ + public function editConsumable($kit_id, $consumable_id) + { + $this->authorize('update', PredefinedKit::class); + if (!($kit = PredefinedKit::find($kit_id))) { + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + if (!($consumable = $kit->consumables()->find($consumable_id))) { + return redirect()->route('kits.index')->with('error', 'Consumable does not exist'); // TODO: trans + } + + return view('kits/consumable-edit', [ + 'kit' => $kit, + 'consumable' => $consumable, + 'item' => $consumable->pivot + ]); + } + + /** + * Update attached consumable + * + * @author [D. Minaev] [] + * @param int $kit_id + * @param int $consumableId + * @return View + */ + public function updateConsumable(Request $request, $kit_id, $consumable_id) + { + + $this->authorize('update', PredefinedKit::class); + if (is_null($kit = PredefinedKit::find($kit_id))) { + // Redirect to the kits management page + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + $validator = \Validator::make($request->all(), $kit->makeConsumableRules($consumable_id)); + + if ($validator->fails()) { + return redirect()->back()->withInput()->withErrors($validator); + } + + $pivot = $kit->consumables()->wherePivot('id', $request->input('pivot_id'))->first()->pivot; + + $pivot->consumable_id = $request->input('consumable_id'); + $pivot->quantity = $request->input('quantity'); + $pivot->save(); + + return redirect()->route('kits.edit', $kit_id)->with('success', 'Consumable updated successfully.'); // TODO: trans + } + + /** + * Remove the consumable from set + * + * @author [D. Minaev] [] + * @param int $consumable_id + * @return View + */ + public function detachConsumable($kit_id, $consumable_id) + { + $this->authorize('update', PredefinedKit::class); + if (is_null($kit = PredefinedKit::find($kit_id))) { + // Redirect to the kits management page + return redirect()->route('kits.index')->with('error', 'Kit does not exist'); // TODO: trans + } + + // Delete childs + $kit->consumables()->detach($consumable_id); + + // Redirect to the kit management page + return redirect()->route('kits.edit', $kit_id)->with('success', 'Consumable was successfully detached'); // TODO: trans + } +} diff --git a/app/Http/Controllers/ModalController.php b/app/Http/Controllers/ModalController.php index c55ad04a4d..168a46e5bb 100644 --- a/app/Http/Controllers/ModalController.php +++ b/app/Http/Controllers/ModalController.php @@ -36,4 +36,19 @@ class ModalController extends Controller return view('modals.manufacturer'); } + function kitModel() { + return view('modals.kit-model'); + } + + function kitLicense() { + return view('modals.kit-license'); + } + + function kitConsumable() { + return view('modals.kit-consumable'); + } + + function kitAccessory() { + return view('modals.kit-accessory'); + } } diff --git a/app/Http/Transformers/PredefinedKitsTransformer.php b/app/Http/Transformers/PredefinedKitsTransformer.php new file mode 100644 index 0000000000..8ff4664f44 --- /dev/null +++ b/app/Http/Transformers/PredefinedKitsTransformer.php @@ -0,0 +1,81 @@ +] + * @return array + */ +class PredefinedKitsTransformer +{ + + public function transformPredefinedKits (Collection $kits, $total) + { + $array = array(); + foreach ($kits as $kit) { + $array[] = self::transformPredefinedKit($kit); + } + return (new DatatablesTransformer)->transformDatatables($array, $total); + } + + public function transformPredefinedKit (PredefinedKit $kit) + { + $array = [ + 'id' => (int) $kit->id, + 'name' => e($kit->name) + ]; + + $permissions_array['available_actions'] = [ + 'update' => Gate::allows('update', PredefinedKit::class), + 'delete' => Gate::allows('delete', PredefinedKit::class), + 'checkout' => Gate::allows('checkout', PredefinedKit::class) ? true : false, + // 'clone' => Gate::allows('create', PredefinedKit::class), + // 'restore' => Gate::allows('create', PredefinedKit::class), + ]; + $array['user_can_checkout'] = true; + $array += $permissions_array; + return $array; + } + + /** + * transform collection of any elemets attached to kit + * @return array + */ + public function transformElements(Collection $elements, $total) { + $array = array(); + foreach ($elements as $element) { + $array[] = self::transformElement($element); + } + return (new DatatablesTransformer)->transformDatatables($array, $total); + } + + public function transformElement(SnipeModel $element) { + $array = [ + 'id' => (int) $element->id, + 'pivot_id' => (int) $element->pivot->id, + 'owner_id' => (int) $element->pivot->kit_id, + 'quantity' => (int) $element->pivot->quantity, + 'name' => e($element->name) + ]; + + $permissions_array['available_actions'] = [ + 'update' => Gate::allows('update', PredefinedKit::class), + 'delete' => Gate::allows('delete', PredefinedKit::class), + ]; + + $array += $permissions_array; + return $array; + } + + public function transformPredefinedKitsDatatable($kits) { + return (new DatatablesTransformer)->transformDatatables($kits); + } + + +} diff --git a/app/Models/PredefinedKit.php b/app/Models/PredefinedKit.php new file mode 100644 index 0000000000..71b7340d38 --- /dev/null +++ b/app/Models/PredefinedKit.php @@ -0,0 +1,187 @@ +] + * @version v1.0 + */ +class PredefinedKit extends SnipeModel +{ + protected $presenter = 'App\Presenters\PredefinedKitPresenter'; + use Presentable; + protected $table = 'kits'; + + /** + * Category validation rules + */ + public $rules = array( + 'name' => 'required|min:1|max:255|unique' + ); + + use ValidatingTrait; + + public $modelRules = [ + 'model_id' => 'required|exists:models,id', + 'quantity' => 'required|integer|min:1', + 'pivot_id' => 'integer|exists:kits_models,id' + ]; + + /** + * this rules use in edit an attached asset model form + * see PredefinedKit::_makeRuleHelper function for details + * @param int $model_id + * @param bool $new = true if append a new element to kit + */ + public function makeModelRules($model_id, $new=false) + { + return $this->_makeRuleHelper('models', 'kits_models', 'model_id', $model_id, $new); + } + + /** + * this rules use in edit an attached license form + * see PredefinedKit::_makeRuleHelper function for details + * @param int $license_id + * @param bool $new = true if append a new element to kit + */ + public function makeLicenseRules($license_id, $new=false) + { + return $this->_makeRuleHelper('licenses', 'kits_licenses', 'license_id', $license_id, $new); + } + + /** + * this rules use in edit an attached accessory form + * see PredefinedKit::_makeRuleHelper function for details + * @param int $accessoriy_id + * @param bool $new = true if append a new element to kit + */ + public function makeAccessoryRules($accessory_id, $new=false) + { + return $this->_makeRuleHelper('accessories', 'kits_accessories', 'accessory_id', $accessory_id, $new); + } + + /** + * this rules use in edit an attached consumable form + * see PredefinedKit::_makeRuleHelper function for details + * @param int $consumable_id + * @param bool $new = true if append a new element to kit + */ + public function makeConsumableRules($consumable_id, $new=false) + { + return $this->_makeRuleHelper('consumables', 'kits_consumables', 'consumable_id', $consumable_id, $new); + } + + /** + * Make rules for validation kit attached elements via Illuminate\Validation\Rule + * checks: + * uniqueness of the record in table for this kit + * existence of record in table + * and simple types check + * @param string $table element table name + * @param string $pivot_table kit+element table name + * @param string $pivot_elem_key element key name inside pivot table + * @param int $element_id + * @param bool $new = true if append a new element to kit + * @return array + */ + protected function _makeRuleHelper($table, $pivot_table, $pivot_elem_key, $element_id, $new) + { + $rule = [ + $pivot_elem_key => [ + 'required', + "exists:$table,id", + Rule::unique($pivot_table)->whereNot($pivot_elem_key, $element_id)->where('kit_id', $this->id) + ], + 'quantity' => 'required|integer|min:1' + ]; + if (!$new) { + $rule['pivot_id'] = "integer|exists:$pivot_table,id"; + + } + return $rule; + } + + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + 'name' + ]; + + use Searchable; + + /** + * The attributes that should be included when searching the kit. + * + * @var array + */ + protected $searchableAttributes = ['name']; + + /** + * The relations and their attributes that should be included when searching the kit. + * + * @var array + */ + protected $searchableRelations = []; + + + /** + * Establishes the kits -> models relationship + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function models() + { + return $this->belongsToMany('\App\Models\AssetModel', 'kits_models', 'kit_id', 'model_id')->withPivot('id', 'quantity'); + } + + public function assets() + { + return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'country_id', 'user_id'); + } + + /** + * Establishes the kits -> licenses relationship + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function licenses() + { + return $this->belongsToMany('\App\Models\License', 'kits_licenses', 'kit_id', 'license_id')->withPivot('id', 'quantity'); + } + + /** + * Establishes the kits -> licenses relationship + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function consumables() + { + return $this->belongsToMany('\App\Models\Consumable', 'kits_consumables', 'kit_id', 'consumable_id')->withPivot('id', 'quantity'); + } + + /** + * Establishes the kits -> licenses relationship + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function accessories() + { + return $this->belongsToMany('\App\Models\Accessory', 'kits_accessories', 'kit_id', 'accessory_id')->withPivot('id', 'quantity'); + } + + /** + * ----------------------------------------------- + * BEGIN QUERY SCOPES + * ----------------------------------------------- + **/ + +} diff --git a/app/Presenters/PredefinedKitPresenter.php b/app/Presenters/PredefinedKitPresenter.php new file mode 100644 index 0000000000..aa8b5e2640 --- /dev/null +++ b/app/Presenters/PredefinedKitPresenter.php @@ -0,0 +1,296 @@ + "id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "name", + "searchable" => true, + "sortable" => true, + "title" => 'Name', // TODO: trans + "formatter" => "kitsLinkFormatter" + ] + ]; + + $layout[] = [ + "field" => "checkincheckout", + "searchable" => false, + "sortable" => false, + "switchable" => true, + "title" => trans('general.checkin').'/'.trans('general.checkout'), + "visible" => true, + "formatter" => "kitsInOutFormatter", + ]; + + $layout[] = [ + "field" => "actions", + "searchable" => false, + "sortable" => false, + "switchable" => false, + "title" => trans('table.actions'), + "formatter" => "kitsActionsFormatter", + ]; + + + return json_encode($layout); + } + + + /** + * Json Column Layout for bootstrap table of kit models + * @return string + */ + public static function dataTableModels() + { + $layout = [ + [ + "field" => "id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "pivot_id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "owner_id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "name", + "searchable" => true, + "sortable" => true, + "title" => 'Name', // TODO: trans + "formatter" => "modelsLinkFormatter" + ], [ + "field" => "quantity", + "searchable" => false, + "sortable" => false, + "title" => 'Quantity', // TODO: trans + ], [ + "field" => "actions", + "searchable" => false, + "sortable" => false, + "switchable" => false, + "title" => trans('table.actions'), + "formatter" => "kits_modelsActionsFormatter", + ] + ]; + + return json_encode($layout); + } + + /** + * Json Column Layout for bootstrap table of kit licenses + * @return string + */ + public static function dataTableLicenses() + { + $layout = [ + [ + "field" => "id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "pivot_id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "owner_id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "name", + "searchable" => true, + "sortable" => true, + "title" => 'Name', // TODO: trans + "formatter" => "licensesLinkFormatter" + ], [ + "field" => "quantity", + "searchable" => false, + "sortable" => false, + "title" => 'Quantity', // TODO: trans + ], [ + "field" => "actions", + "searchable" => false, + "sortable" => false, + "switchable" => false, + "title" => trans('table.actions'), + "formatter" => "kits_licensesActionsFormatter", + ] + ]; + + return json_encode($layout); + } + + /** + * Json Column Layout for bootstrap table of kit accessories + * @return string + */ + public static function dataTableAccessories() + { + $layout = [ + [ + "field" => "id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "pivot_id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "owner_id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "name", + "searchable" => true, + "sortable" => true, + "title" => 'Name', // TODO: trans + "formatter" => "accessoriesLinkFormatter" + ], [ + "field" => "quantity", + "searchable" => false, + "sortable" => false, + "title" => 'Quantity', // TODO: trans + ], [ + "field" => "actions", + "searchable" => false, + "sortable" => false, + "switchable" => false, + "title" => trans('table.actions'), + "formatter" => "kits_accessoriesActionsFormatter", + ] + ]; + + return json_encode($layout); + } + + + /** + * Json Column Layout for bootstrap table of kit consumables + * @return string + */ + public static function dataTableConsumables() + { + $layout = [ + [ + "field" => "id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "pivot_id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "owner_id", + "searchable" => false, + "sortable" => true, + "switchable" => true, + "title" => trans('general.id'), + "visible" => false + ], [ + "field" => "name", + "searchable" => true, + "sortable" => true, + "title" => 'Name', // TODO: trans + "formatter" => "consumablesLinkFormatter" + ], [ + "field" => "quantity", + "searchable" => false, + "sortable" => false, + "title" => 'Quantity', // TODO: trans + ], [ + "field" => "actions", + "searchable" => false, + "sortable" => false, + "switchable" => false, + "title" => trans('table.actions'), + "formatter" => "kits_consumablesActionsFormatter", + ] + ]; + + return json_encode($layout); + } + + + /** + * Link to this kit Name + * @return string + */ + public function nameUrl() + { + return (string)link_to_route('kits.show', $this->name, $this->id); + } + + /** + * @return string + */ + public function fullName() + { + return $this->name; + } + + /** + * Url to view this item. + * @return string + */ + public function viewUrl() + { + return route('kits.show', $this->id); + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 94f5ca0bf3..02bf3dc072 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -63,6 +63,7 @@ class RouteServiceProvider extends ServiceProvider require base_path('routes/web/fields.php'); require base_path('routes/web/components.php'); require base_path('routes/web/users.php'); + require base_path('routes/web/kits.php'); require base_path('routes/web.php'); }); } diff --git a/app/Services/PredefinedKitCheckoutService.php b/app/Services/PredefinedKitCheckoutService.php new file mode 100644 index 0000000000..abc95b31a9 --- /dev/null +++ b/app/Services/PredefinedKitCheckoutService.php @@ -0,0 +1,194 @@ +] + */ +class PredefinedKitCheckoutService +{ + use AuthorizesRequests; + /** + * @param Request $request, this function works with fields: checkout_at, expected_checkin, note + * @param PredefinedKit $kit kit for checkout + * @param User $user checkout target + * @return array Empty array if all ok, else [string_error1, string_error2...] + */ + public function checkout(Request $request, PredefinedKit $kit, User $user) + { + try { + + // Check if the user exists + if (is_null($user)) { + return [trans('admin/users/message.user_not_found')]; + } + + $errors = []; + + $assets_to_add = $this->getAssetsToAdd($kit, $user, $errors); + $license_seats_to_add = $this->getLicenseSeatsToAdd($kit, $errors); + $consumables_to_add = $this->getConsumablesToAdd($kit, $errors); + $accessories_to_add = $this->getAccessoriesToAdd($kit, $errors); + + if (count($errors) > 0) { + return $errors; + } + + $checkout_at = date("Y-m-d H:i:s"); + if (($request->filled('checkout_at')) && ($request->get('checkout_at') != date("Y-m-d"))) { + $checkout_at = $request->get('checkout_at'); + } + + $expected_checkin = ''; + if ($request->filled('expected_checkin')) { + $expected_checkin = $request->get('expected_checkin'); + } + + $admin = Auth::user(); + + $note = e($request->get('note')); + + $errors = $this->saveToDb($user, $admin, $checkout_at, $expected_checkin, $errors, $assets_to_add, $license_seats_to_add, $consumables_to_add, $accessories_to_add, $note); + return $errors; + } catch (ModelNotFoundException $e) { + return [$e->getMessage()]; + } catch (CheckoutNotAllowed $e) { + return [$e->getMessage()]; + } + } + + protected function getAssetsToAdd($kit, $user, &$errors) + { + $models = $kit->models() + ->with(['assets' => function ($hasMany) { + $hasMany->RTD(); + }]) + ->get(); + $assets_to_add = []; + foreach ($models as $model) { + $assets = $model->assets; + $quantity = $model->pivot->quantity; + foreach ($assets as $asset) { + + if ( + $asset->availableForCheckout() + && !$asset->is($user) + ) { + + $this->authorize('checkout', $asset); + $quantity -= 1; + $assets_to_add[] = $asset; + if ($quantity <= 0) { + break; + } + } + } + if ($quantity > 0) { + $errors[] = "Don't have available assets for model " . $model->name . '. Need ' . $model->pivot->quantity . ' assets.'; // TODO: trans + } + } + + return $assets_to_add; + } + + protected function getLicenseSeatsToAdd($kit, &$errors) + { + $seats_to_add = []; + $licenses = $kit->licenses() + ->with('freeSeats') + ->get(); + foreach ($licenses as $license) { + $quantity = $license->pivot->quantity; + if ($quantity > count($license->freeSeats)) { + $errors[] = "Don't have free seats for license " . $license->name . '. Need ' . $quantity . ' seats.'; // TODO: trans + } + for ($i = 0; $i < $quantity; $i++) { + $seats_to_add[] = $license->freeSeats[$i]; + } + } + return $seats_to_add; + } + + protected function getConsumablesToAdd($kit, &$errors) + { + // $consumables = $kit->consumables()->withCount('consumableAssignments as consumable_assignments_count')->get(); + $consumables = $kit->consumables()->with('users')->get(); + foreach ($consumables as $consumable) { + if ($consumable->numRemaining() < $consumable->pivot->quantity) { + $errors[] = "Don't have available consumable " . $consumable->name . '. Need ' . $consumable->pivot->quantity; // TODO: trans + } + } + return $consumables; + } + + protected function getAccessoriesToAdd($kit, &$errors) + { + $accessories = $kit->accessories()->with('users')->get(); + foreach ($accessories as $accossory) { + if ($accossory->numRemaining() < $accossory->pivot->quantity) { + $errors[] = "Don't have available accossory " . $accossory->name . '. Need ' . $accossory->pivot->quantity; // TODO: trans + } + } + return $accessories; + } + + protected function saveToDb($user, $admin, $checkout_at, $expected_checkin, $errors, $assets_to_add, $license_seats_to_add, $consumables_to_add, $accessories_to_add, $note) + { + $errors = DB::transaction( + function () use ($user, $admin, $checkout_at, $expected_checkin, $errors, $assets_to_add, $license_seats_to_add, $consumables_to_add, $accessories_to_add, $note) { + // assets + foreach ($assets_to_add as $asset) { + $asset->location_id = $user->location_id; + $error = $asset->checkOut($user, $admin, $checkout_at, $expected_checkin, $note, null); + if ($error) { + array_merge_recursive($errors, $asset->getErrors()->toArray()); + } + } + // licenses + foreach ($license_seats_to_add as $licenseSeat) { + $licenseSeat->user_id = $admin->id; + $licenseSeat->assigned_to = $user->id; + if ($licenseSeat->save()) { + event(new CheckoutableCheckedOut($licenseSeat, $user, $admin, $note)); + } else { + $errors[] = 'Something went wrong saving a license seat'; + } + } + // consumables + foreach ($consumables_to_add as $consumable) { + $consumable->assigned_to = $user->id; + $consumable->users()->attach($consumable->id, [ + 'consumable_id' => $consumable->id, + 'user_id' => $admin->id, + 'assigned_to' => $user->id + ]); + event(new CheckoutableCheckedOut($consumable, $user, $admin, $note)); + } + //accessories + foreach ($accessories_to_add as $accessory) { + $accessory->assigned_to = $user->id; + $accessory->users()->attach($accessory->id, [ + 'accessory_id' => $accessory->id, + 'user_id' => $admin->id, + 'assigned_to' => $user->id + ]); + event(new CheckoutableCheckedOut($accessory, $user, $admin, $note)); + } + return $errors; + } + ); + + return $errors; + } +} diff --git a/database/migrations/2018_10_18_191228_add_kits_licenses_table.php b/database/migrations/2018_10_18_191228_add_kits_licenses_table.php new file mode 100644 index 0000000000..44ca2c0a24 --- /dev/null +++ b/database/migrations/2018_10_18_191228_add_kits_licenses_table.php @@ -0,0 +1,36 @@ +increments('id'); + $table->integer('kit_id')->nullable()->default(NULL); + $table->integer('license_id')->nullable()->default(NULL); + $table->integer('quantity')->default(1); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + Schema::drop('kits_licenses'); + } + +} diff --git a/database/migrations/2018_10_19_153910_add_kits_table.php b/database/migrations/2018_10_19_153910_add_kits_table.php new file mode 100644 index 0000000000..949c150146 --- /dev/null +++ b/database/migrations/2018_10_19_153910_add_kits_table.php @@ -0,0 +1,37 @@ +increments('id'); + $table->string('name')->nullable()->default(NULL); + $table->timestamps(); + $table->engine = 'InnoDB'; + }); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + Schema::drop('kits'); + + } + +} diff --git a/database/migrations/2018_10_19_154013_add_kits_models_table.php b/database/migrations/2018_10_19_154013_add_kits_models_table.php new file mode 100644 index 0000000000..a0abeeef7b --- /dev/null +++ b/database/migrations/2018_10_19_154013_add_kits_models_table.php @@ -0,0 +1,36 @@ +increments('id'); + $table->integer('kit_id')->nullable()->default(NULL); + $table->integer('model_id')->nullable()->default(NULL); + $table->integer('quantity')->default(1); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + Schema::drop('kits_models'); + } + +} diff --git a/database/migrations/2019_02_07_185953_add_kits_consumables_table.php b/database/migrations/2019_02_07_185953_add_kits_consumables_table.php new file mode 100644 index 0000000000..b6d14e4285 --- /dev/null +++ b/database/migrations/2019_02_07_185953_add_kits_consumables_table.php @@ -0,0 +1,36 @@ +increments('id'); + $table->integer('kit_id')->nullable()->default(NULL); + $table->integer('consumable_id')->nullable()->default(NULL); + $table->integer('quantity')->default(1); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + Schema::drop('kits_consumables'); + } +} diff --git a/database/migrations/2019_02_07_190030_add_kits_accessories_table.php b/database/migrations/2019_02_07_190030_add_kits_accessories_table.php new file mode 100644 index 0000000000..f0e80249db --- /dev/null +++ b/database/migrations/2019_02_07_190030_add_kits_accessories_table.php @@ -0,0 +1,36 @@ +increments('id'); + $table->integer('kit_id')->nullable()->default(NULL); + $table->integer('accessory_id')->nullable()->default(NULL); + $table->integer('quantity')->default(1); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + Schema::drop('kits_accessories'); + } +} diff --git a/resources/assets/js/snipeit_modals.js b/resources/assets/js/snipeit_modals.js index 56fcdcbc28..30791ce425 100644 --- a/resources/assets/js/snipeit_modals.js +++ b/resources/assets/js/snipeit_modals.js @@ -28,7 +28,7 @@ $(function () { //handle modal-add-interstitial calls - var model, select; + var model, select, refreshSelector; if($('#createModal').length == 0) { $('body').append(''); @@ -38,6 +38,8 @@ $(function () { var link = $(event.relatedTarget); model = link.data("dependency"); select = link.data("select"); + refreshSelector = link.data("refresh"); + $('#createModal').load(link.attr('href'),function () { //do we need to re-select2 this, after load? Probably. $('#createModal').find('select.select2').select2(); @@ -123,6 +125,12 @@ $(function () { $('#createModal').modal('hide'); $('#createModal').html(""); + var refreshTable = $('#' + refreshSelector); + + if(refreshTable.length > 0) { + refreshTable.bootstrapTable('refresh'); + } + // "select" is the original drop-down menu that someone // clicked 'add' on to add a new 'thing' // this code adds the newly created object to that select diff --git a/resources/views/kits/accessory-edit.blade.php b/resources/views/kits/accessory-edit.blade.php new file mode 100644 index 0000000000..e25966f7f5 --- /dev/null +++ b/resources/views/kits/accessory-edit.blade.php @@ -0,0 +1,23 @@ +@extends('layouts/edit-form', [ + 'createText' => 'Append accessory', // TODO: trans + 'updateText' => 'Update appended accessory', // TODO: trans + 'formAction' => ($item) ? route('kits.accessories.update', ['kit_id' => $kit->id, 'accessory_id' => $item->accessory_id]) : route('kits.accessories.store', ['kit_id' => $kit->id]), +]) + +{{-- Page content --}} +@section('inputFields') +@include ('partials.forms.edit.accessory-select', ['translated_name' => 'Accessory', 'fieldname' => 'accessory_id', 'required' => 'true']){{-- TODO: trans --}} +
+ +
+
+ +
+ {!! $errors->first('quantity', ' :message') !!} +
+
+ + +{{-- --}} + +@stop diff --git a/resources/views/kits/checkout.blade.php b/resources/views/kits/checkout.blade.php new file mode 100644 index 0000000000..d9ca25f55f --- /dev/null +++ b/resources/views/kits/checkout.blade.php @@ -0,0 +1,97 @@ +@extends('layouts/default') + +{{-- Page title --}} +@section('title') + Apply predefined kit{{-- TODO: trans --}} +@parent +@stop + +{{-- Page content --}} +@section('content') + + + + +
+ +
+
+
+

Apply predefined kit {{ $kit->name }} to user {{-- TODO: trans --}}

+
+
+
+ {{ csrf_field() }} + @include ('partials.forms.edit.user-select', ['translated_name' => trans('general.select_user'), 'fieldname' => 'user_id', 'required'=> 'true']) + + +
+ {{ Form::label('name', trans('admin/hardware/form.checkout_date'), array('class' => 'col-md-3 control-label')) }} +
+
+ + +
+ {!! $errors->first('checkout_at', ' :message') !!} +
+
+ + +
+ {{ Form::label('name', trans('admin/hardware/form.expected_checkin'), array('class' => 'col-md-3 control-label')) }} +
+
+ + +
+ {!! $errors->first('expected_checkin', ' :message') !!} +
+
+ + + +
+ {{ Form::label('note', trans('admin/hardware/form.notes'), array('class' => 'col-md-3 control-label')) }} +
+ + {!! $errors->first('note', ' :message') !!} +
+
+ +
+ +
+ +
+ + + +
+@stop + +@section('moar_scripts') +@include('partials/assets-assigned') + +@stop + +@section('notifications') +@parent + +@stop diff --git a/resources/views/kits/consumable-edit.blade.php b/resources/views/kits/consumable-edit.blade.php new file mode 100644 index 0000000000..896b8c37d4 --- /dev/null +++ b/resources/views/kits/consumable-edit.blade.php @@ -0,0 +1,24 @@ +@extends('layouts/edit-form', [ + 'createText' => 'Append consumable', // TODO: trans + 'updateText' => 'Update appended consumable', // TODO: trans + 'formAction' => ($item) ? route('kits.consumables.update', ['kit_id' => $kit->id, 'consumable_id' => $item->consumable_id]) : route('kits.consumables.store', ['kit_id' => $kit->id]), +]) + +{{-- Page content --}} +@section('inputFields') +@include ('partials.forms.edit.consumable-select', ['translated_name' => 'Consumable', 'fieldname' => 'consumable_id', 'required' => 'true']){{-- TODO: trans --}} + +
+ +
+
+ +
+ {!! $errors->first('quantity', ' :message') !!} +
+
+ + +{{-- --}} + +@stop diff --git a/resources/views/kits/create.blade.php b/resources/views/kits/create.blade.php new file mode 100644 index 0000000000..4be2bb5dca --- /dev/null +++ b/resources/views/kits/create.blade.php @@ -0,0 +1,10 @@ +@extends('layouts/edit-form', [ + 'createText' => 'Create kit', + 'updateText' => 'Update kit', + 'formAction' => ($item) ? route('kits.update', ['kit' => $item->id]) : route('kits.store'), +]) + +{{-- Page content --}} +@section('inputFields') +@include ('partials.forms.edit.name', ['translated_name' => 'Name']) {{-- TODO: trans --}} +@stop \ No newline at end of file diff --git a/resources/views/kits/edit.blade.php b/resources/views/kits/edit.blade.php new file mode 100644 index 0000000000..7d26142d02 --- /dev/null +++ b/resources/views/kits/edit.blade.php @@ -0,0 +1,155 @@ +@extends('layouts/edit-form', [ + 'createText' => 'Create kit', + 'updateText' => 'Update kit', + 'formAction' => ($item) ? route('kits.update', ['kit' => $item->id]) : route('kits.store'), +]) + +{{-- Page content --}} +@section('inputFields') +@include ('partials.forms.edit.name', ['translated_name' => 'Name']) {{-- TODO: trans --}} +@stop + +@section('content') +@parent +{{-- Assets by model --}} +
+
+
+
+ {{--

Models Append

--}} +

Assets (by models){{-- TODO: trans --}}

+
+
+
+ +
+ Append +
+
+
+
+
+{{-- Licenses --}} +
+
+
+
+

Licenses{{-- TODO: trans --}}

+
+ +
+
+
+{{-- Consumables --}} +
+
+
+
+

Consumables{{-- TODO: trans --}}

+
+ +
+
+
+{{-- Accessories --}} +
+
+
+
+

Accessories{{-- TODO: trans --}}

+
+ +
+
+
+@stop + +@section('moar_scripts') +@include ('partials.bootstrap-table') +@stop \ No newline at end of file diff --git a/resources/views/kits/index.blade.php b/resources/views/kits/index.blade.php new file mode 100644 index 0000000000..6cf41e73f7 --- /dev/null +++ b/resources/views/kits/index.blade.php @@ -0,0 +1,71 @@ +@extends('layouts/default') + +{{-- Web site Title --}} +@section('title') +Kits +@parent +@stop + +@section('header_right') +{{ trans('general.create') }} +@stop + + +{{-- Content --}} +@section('content') +
+
+
+
+
+ + +
+
+ {{--

Test

+
+ +
+
--}} +
+
+
+
+@stop +@section('moar_scripts') +@include ('partials.bootstrap-table', ['exportFile' => 'kits-export', 'search' => true]) +@stop diff --git a/resources/views/kits/license-edit.blade.php b/resources/views/kits/license-edit.blade.php new file mode 100644 index 0000000000..f64678d9d6 --- /dev/null +++ b/resources/views/kits/license-edit.blade.php @@ -0,0 +1,23 @@ +@extends('layouts/edit-form', [ + 'createText' => 'Append license', // TODO: trans + 'updateText' => 'Update appended license', // TODO: trans + 'formAction' => ($item) ? route('kits.licenses.update', ['kit_id' => $kit->id, 'license_id' => $item->license_id]) : route('kits.licenses.store', ['kit_id' => $kit->id]), +]) + +{{-- Page content --}} +@section('inputFields') +@include ('partials.forms.edit.license-select', ['translated_name' => trans('general.license'), 'fieldname' => 'license_id', 'required' => 'true']) +
+ +
+
+ +
+ {!! $errors->first('quantity', ' :message') !!} +
+
+ + +{{-- --}} + +@stop diff --git a/resources/views/kits/model-edit.blade.php b/resources/views/kits/model-edit.blade.php new file mode 100644 index 0000000000..61a419c958 --- /dev/null +++ b/resources/views/kits/model-edit.blade.php @@ -0,0 +1,23 @@ +@extends('layouts/edit-form', [ + 'createText' => 'Append model', // TODO: trans + 'updateText' => 'Update appended model', // TODO: trans + 'formAction' => ($item) ? route('kits.models.update', ['kit_id' => $kit->id, 'model_id' => $item->model_id]) : route('kits.models.store', ['kit_id' => $kit->id]), +]) + +{{-- Page content --}} +@section('inputFields') +@include ('partials.forms.edit.model-select', ['translated_name' => trans('admin/hardware/form.model'), 'fieldname' => 'model_id', 'required' => 'true']) +
+ +
+
+ +
+ {!! $errors->first('quantity', ' :message') !!} +
+
+ + +{{-- --}} + +@stop diff --git a/resources/views/layouts/default.blade.php b/resources/views/layouts/default.blade.php index ef937d0f0f..44ba4d49ad 100644 --- a/resources/views/layouts/default.blade.php +++ b/resources/views/layouts/default.blade.php @@ -664,6 +664,13 @@ @endcan + + + + + Predefined kits{{-- TODO: trans --}} + + diff --git a/resources/views/modals/kit-accessory.blade.php b/resources/views/modals/kit-accessory.blade.php new file mode 100644 index 0000000000..654116a445 --- /dev/null +++ b/resources/views/modals/kit-accessory.blade.php @@ -0,0 +1,38 @@ +{{-- See snipeit_modals.js for what powers this --}} + diff --git a/resources/views/modals/kit-consumable.blade.php b/resources/views/modals/kit-consumable.blade.php new file mode 100644 index 0000000000..ae948b8500 --- /dev/null +++ b/resources/views/modals/kit-consumable.blade.php @@ -0,0 +1,38 @@ +{{-- See snipeit_modals.js for what powers this --}} + diff --git a/resources/views/modals/kit-license.blade.php b/resources/views/modals/kit-license.blade.php new file mode 100644 index 0000000000..e3306ae867 --- /dev/null +++ b/resources/views/modals/kit-license.blade.php @@ -0,0 +1,38 @@ +{{-- See snipeit_modals.js for what powers this --}} + diff --git a/resources/views/modals/kit-model.blade.php b/resources/views/modals/kit-model.blade.php new file mode 100644 index 0000000000..1800184a73 --- /dev/null +++ b/resources/views/modals/kit-model.blade.php @@ -0,0 +1,38 @@ +{{-- See snipeit_modals.js for what powers this --}} + diff --git a/resources/views/notifications.blade.php b/resources/views/notifications.blade.php index dff9ab9531..4ba0bcae96 100755 --- a/resources/views/notifications.blade.php +++ b/resources/views/notifications.blade.php @@ -45,6 +45,19 @@ @endif +@if ($messages = Session::get('error_messages')) +@foreach ($messages as $message) +
+
+ + + Error: + {{ $message }} +
+
+@endforeach +@endif + @if ($message = Session::get('warning'))
diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php index 20345aeb47..b3ac89a902 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -150,22 +150,26 @@ } // Make the edit/delete buttons - function genericActionsFormatter(destination) { + function genericActionsFormatter(owner_name, element_name = '') { return function (value,row) { var actions = ''; // Add some overrides for any funny urls we have - var dest = destination; + var dest = owner_name; - if (destination=='groups') { + if (dest =='groups') { var dest = 'admin/groups'; } - if (destination=='maintenances') { + if (dest =='maintenances') { var dest = 'hardware/maintenances'; } + if(element_name != '') { + dest = dest + '/' + row.owner_id + '/' + element_name; + } + if ((row.available_actions) && (row.available_actions.clone === true)) { actions += ' '; } @@ -323,7 +327,8 @@ 'companies', 'depreciations', 'fieldsets', - 'groups' + 'groups', + 'kits' ]; for (var i in formatters) { @@ -333,6 +338,20 @@ window[formatters[i] + 'InOutFormatter'] = genericCheckinCheckoutFormatter(formatters[i]); } + var child_formatters = [ + ['kits', 'models'], + ['kits', 'licenses'], + ['kits', 'consumables'], + ['kits', 'accessories'], + ]; + + for (var i in child_formatters) { + var owner_name = child_formatters[i][0]; + var child_name = child_formatters[i][1]; + window[owner_name + '_' + child_name + 'ActionsFormatter'] = genericActionsFormatter(owner_name, child_name); + } + + // This is gross, but necessary so that we can package the API response // for custom fields in a more useful way. diff --git a/resources/views/partials/forms/edit/accessory-select.blade.php b/resources/views/partials/forms/edit/accessory-select.blade.php new file mode 100644 index 0000000000..e786717ed8 --- /dev/null +++ b/resources/views/partials/forms/edit/accessory-select.blade.php @@ -0,0 +1,20 @@ + +
+ {{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }} +
+ +
+ {!! $errors->first($fieldname, '
:message
') !!} + +
diff --git a/resources/views/partials/forms/edit/consumable-select.blade.php b/resources/views/partials/forms/edit/consumable-select.blade.php new file mode 100644 index 0000000000..28cc56415d --- /dev/null +++ b/resources/views/partials/forms/edit/consumable-select.blade.php @@ -0,0 +1,20 @@ + +
+ {{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }} +
+ +
+ {!! $errors->first($fieldname, '
:message
') !!} + +
diff --git a/resources/views/partials/forms/edit/kit-select.blade.php b/resources/views/partials/forms/edit/kit-select.blade.php new file mode 100644 index 0000000000..3bf251263d --- /dev/null +++ b/resources/views/partials/forms/edit/kit-select.blade.php @@ -0,0 +1,27 @@ +
+ + {{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }} + +
+ +
+ +
+ @can('create', \App\Models\PredefinedKit::class) + @if ((!isset($hide_new)) || ($hide_new!='true')) + {{-- New --}} + @endif + @endcan +
+ + {!! $errors->first($fieldname, '
:message
') !!} + +
diff --git a/resources/views/partials/forms/edit/license-select.blade.php b/resources/views/partials/forms/edit/license-select.blade.php new file mode 100644 index 0000000000..ecb07e0740 --- /dev/null +++ b/resources/views/partials/forms/edit/license-select.blade.php @@ -0,0 +1,20 @@ + +
+ {{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }} +
+ +
+ {!! $errors->first($fieldname, '
:message
') !!} + +
diff --git a/routes/api.php b/routes/api.php index da58760578..ef0488c7bf 100644 --- a/routes/api.php +++ b/routes/api.php @@ -33,7 +33,23 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () { }); - /*--- Accessories API ---*/ + /*--- Accessories API ---*/ + Route::group(['prefix' => 'accessories'], function () { + + Route::get('{accessory}/checkedout', + [ + 'as' => 'api.accessories.checkedout', + 'uses' => 'AccessoriesController@checkedout' + ] + ); + + Route::get('selectlist', + [ + 'as' => 'api.accessories.selectlist', + 'uses'=> 'AccessoriesController@selectlist' + ] + ); + }); // Accessories group Route::resource('accessories', 'AccessoriesController', ['names' => [ @@ -48,15 +64,7 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () { ] ); // Accessories resource - Route::group(['prefix' => 'accessories'], function () { - Route::get('{accessory}/checkedout', - [ - 'as' => 'api.accessories.checkedout', - 'uses' => 'AccessoriesController@checkedout' - ] - ); - }); // Accessories group /*--- Categories API ---*/ @@ -174,7 +182,12 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () { /*--- Consumables API ---*/ - + Route::get('consumables/selectlist', + [ + 'as' => 'api.consumables.selectlist', + 'uses'=> 'ConsumablesController@selectlist' + ] + ); Route::resource('consumables', 'ConsumablesController', [ 'names' => @@ -419,6 +432,14 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () { 'as' => 'api.license.seats', 'uses' => 'LicensesController@seats' ]); + + Route::get('selectlist', + [ + 'as' => 'api.licenses.selectlist', + 'uses'=> 'LicensesController@selectlist' + ] + ); + }); // Licenses group Route::resource('licenses', 'LicensesController', @@ -772,6 +793,142 @@ Route::group(['prefix' => 'v1','namespace' => 'Api'], function () { [ 'as' => 'api.activity.index', 'uses' => 'ReportsController@index' ] ); + /*--- Kits API ---*/ + + Route::resource('kits', 'PredefinedKitsController', + [ + 'names' => + [ + 'index' => 'api.kits.index', + 'show' => 'api.kits.show', + 'store' => 'api.kits.store', + 'update' => 'api.kits.update', + 'destroy' => 'api.kits.destroy', + ], + 'except' => ['create', 'edit'], + 'parameters' => ['kit' => 'kit_id'] + ] + ); + Route::group([ 'prefix' => 'kits/{kit_id}' ], function () { + + // kit licenses + Route::get('licenses', + [ + 'as' => 'api.kits.licenses.index', + 'uses' => 'PredefinedKitsController@indexLicenses', + ] + ); + + Route::post('licenses', + [ + 'as' => 'api.kits.licenses.store', + 'uses' => 'PredefinedKitsController@storeLicense', + ] + ); + + Route::put('licenses/{license_id}', + [ + 'as' => 'api.kits.licenses.update', + 'uses' => 'PredefinedKitsController@updateLicense', + ] + ); + + Route::delete('licenses/{license_id}', + [ + 'as' => 'api.kits.licenses.destroy', + 'uses' => 'PredefinedKitsController@detachLicense', + ] + ); + + // kit models + Route::get('models', + [ + 'as' => 'api.kits.models.index', + 'uses' => 'PredefinedKitsController@indexModels', + ] + ); + + Route::post('models', + [ + 'as' => 'api.kits.models.store', + 'uses' => 'PredefinedKitsController@storeModel', + ] + ); + + Route::put('models/{model_id}', + [ + 'as' => 'api.kits.models.update', + 'uses' => 'PredefinedKitsController@updateModel', + ] + ); + + Route::delete('models/{model_id}', + [ + 'as' => 'api.kits.models.destroy', + 'uses' => 'PredefinedKitsController@detachModel', + ] + ); + + // kit accessories + Route::get('accessories', + [ + 'as' => 'api.kits.accessories.index', + 'uses' => 'PredefinedKitsController@indexAccessories', + ] + ); + + Route::post('accessories', + [ + 'as' => 'api.kits.accessories.store', + 'uses' => 'PredefinedKitsController@storeAccessory', + ] + ); + + Route::put('accessories/{accessory_id}', + [ + 'as' => 'api.kits.accessories.update', + 'uses' => 'PredefinedKitsController@updateAccessory', + ] + ); + + Route::delete('accessories/{accessory_id}', + [ + 'as' => 'api.kits.accessories.destroy', + 'uses' => 'PredefinedKitsController@detachAccessory', + ] + ); + + // kit consumables + Route::get('consumables', + [ + 'as' => 'api.kits.consumables.index', + 'uses' => 'PredefinedKitsController@indexConsumables', + ] + ); + + Route::post('consumables', + [ + 'as' => 'api.kits.consumables.store', + 'uses' => 'PredefinedKitsController@storeConsumable', + ] + ); + + Route::put('consumables/{consumable_id}', + [ + 'as' => 'api.kits.consumables.update', + 'uses' => 'PredefinedKitsController@updateConsumable', + ] + ); + + Route::delete('consumables/{consumable_id}', + [ + 'as' => 'api.kits.consumables.destroy', + 'uses' => 'PredefinedKitsController@detachConsumable', + ] + ); + + }); // kits + }); diff --git a/routes/web.php b/routes/web.php index f59362c767..7ecc4b1fe8 100644 --- a/routes/web.php +++ b/routes/web.php @@ -87,6 +87,10 @@ Route::group(['middleware' => 'auth','prefix' => 'modals'], function () { Route::get('statuslabel',['as' => 'modal.statuslabel','uses' => 'ModalController@statuslabel']); Route::get('supplier',['as' => 'modal.supplier','uses' => 'ModalController@supplier']); Route::get('user',['as' => 'modal.user','uses' => 'ModalController@user']); + Route::get('kit-model',['as' => 'modal.kit.model','uses' => 'ModalController@kitModel']); + Route::get('kit-license',['as' => 'modal.kit.license','uses' => 'ModalController@kitLicense']); + Route::get('kit-consumable',['as' => 'modal.kit.consumable','uses' => 'ModalController@kitConsumable']); + Route::get('kit-accessory',['as' => 'modal.kit.accessory','uses' => 'ModalController@kitAccessory']); }); /* diff --git a/routes/web/kits.php b/routes/web/kits.php new file mode 100644 index 0000000000..50712aba43 --- /dev/null +++ b/routes/web/kits.php @@ -0,0 +1,137 @@ + ['auth'], + 'parameters' => ['kit' => 'kit_id'] +]); + + + +Route::group([ 'prefix' => 'kits/{kit_id}', 'middleware' => ['auth'] ], function () { + + // Route::get('licenses', + // [ + // 'as' => 'kits.licenses.index', + // 'uses' => 'Kits\PredefinedKitsController@indexLicenses', + // ] + // ); + + Route::post('licenses', + [ + 'as' => 'kits.licenses.store', + 'uses' => 'Kits\PredefinedKitsController@storeLicense', + ] + ); + + Route::put('licenses/{license_id}', + [ + 'as' => 'kits.licenses.update', + 'uses' => 'Kits\PredefinedKitsController@updateLicense', + ] + ); + + Route::get('licenses/{license_id}/edit', + [ + 'as' => 'kits.licenses.edit', + 'uses' => 'Kits\PredefinedKitsController@editLicense', + + ] + ); + + Route::delete('licenses/{license_id}', + [ + 'as' => 'kits.licenses.detach', + 'uses' => 'Kits\PredefinedKitsController@detachLicense', + ] + ); + + + // Models + + Route::put('models/{model_id}', + [ + 'as' => 'kits.models.update', + 'uses' => 'Kits\PredefinedKitsController@updateModel', + 'parameters' => [2 => 'kit_id', 1 => 'model_id'] + ] + ); + + Route::get('models/{model_id}/edit', + [ + 'as' => 'kits.models.edit', + 'uses' => 'Kits\PredefinedKitsController@editModel', + + ] + ); + + Route::delete('models/{model_id}', + [ + 'as' => 'kits.models.detach', + 'uses' => 'Kits\PredefinedKitsController@detachModel', + ] + ); + + + // Consumables + Route::put('consumables/{consumable_id}', + [ + 'as' => 'kits.consumables.update', + 'uses' => 'Kits\PredefinedKitsController@updateConsumable', + 'parameters' => [2 => 'kit_id', 1 => 'consumable_id'] + ] + ); + + Route::get('consumables/{consumable_id}/edit', + [ + 'as' => 'kits.consumables.edit', + 'uses' => 'Kits\PredefinedKitsController@editConsumable', + + ] + ); + + Route::delete('consumables/{consumable_id}', + [ + 'as' => 'kits.consumables.detach', + 'uses' => 'Kits\PredefinedKitsController@detachConsumable', + ] + ); + + + // Accessories + Route::put('accessories/{accessory_id}', + [ + 'as' => 'kits.accessories.update', + 'uses' => 'Kits\PredefinedKitsController@updateAccessory', + 'parameters' => [2 => 'kit_id', 1 => 'accessory_id'] + ] + ); + + Route::get('accessories/{accessory_id}/edit', + [ + 'as' => 'kits.accessories.edit', + 'uses' => 'Kits\PredefinedKitsController@editAccessory', + + ] + ); + + Route::delete('accessories/{accessory_id}', + [ + 'as' => 'kits.accessories.detach', + 'uses' => 'Kits\PredefinedKitsController@detachAccessory', + ] + ); + Route::get('checkout', + [ + 'as' => 'kits.checkout.show', + 'uses' => 'Kits\CheckoutKitController@showCheckout', + ] + ); + + Route::post('checkout', + [ + 'as' => 'kits.checkout.store', + 'uses' => 'Kits\CheckoutKitController@store', + ] + ); +}); // kits \ No newline at end of file