2016-03-25 15:50:08 -07:00
< ? php
2016-04-07 13:21:09 -07:00
namespace App\Http\Controllers ;
2016-03-25 01:18:05 -07:00
use App\Helpers\Helper ;
use App\Models\Actionlog ;
use App\Models\Company ;
use App\Models\Consumable ;
use App\Models\Setting ;
use App\Models\User ;
use Auth ;
use Config ;
use DB ;
use Input ;
use Lang ;
use Mail ;
use Redirect ;
use Slack ;
use Str ;
use View ;
2016-04-07 13:21:09 -07:00
/**
* This controller handles all actions related to Consumables for
* the Snipe - IT Asset Management application .
*
* @ version v1 . 0
*/
2016-03-25 01:18:05 -07:00
class ConsumablesController extends Controller
{
/**
2016-03-28 22:51:49 -07:00
* Return a view to display component information .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ see ConsumablesController :: getDatatable () method that generates the JSON response
* @ since [ v1 . 0 ]
* @ return View
*/
2016-03-25 01:18:05 -07:00
public function getIndex ()
{
return View :: make ( 'consumables/index' );
}
/**
2016-03-28 22:51:49 -07:00
* Return a view to display the form view to create a new consumable
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ see ConsumablesController :: postCreate () method that stores the form data
* @ since [ v1 . 0 ]
* @ return View
*/
2016-03-25 01:18:05 -07:00
public function getCreate ()
{
// Show the page
2016-06-05 07:47:44 -07:00
$category_list = Helper :: categoryList ( 'consumable' );
2016-03-25 01:18:05 -07:00
$company_list = Helper :: companyList ();
$location_list = Helper :: locationsList ();
2016-05-16 17:11:31 -07:00
$manufacturer_list = Helper :: manufacturerList ();
2016-03-25 01:18:05 -07:00
return View :: make ( 'consumables/edit' )
-> with ( 'consumable' , new Consumable )
-> with ( 'category_list' , $category_list )
-> with ( 'company_list' , $company_list )
2016-05-16 17:11:31 -07:00
-> with ( 'location_list' , $location_list )
-> with ( 'manufacturer_list' , $manufacturer_list );
2016-03-25 01:18:05 -07:00
}
/**
2016-03-28 22:51:49 -07:00
* Validate and store new consumable data .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ see ConsumablesController :: getCreate () method that returns the form view
* @ since [ v1 . 0 ]
* @ return Redirect
*/
2016-03-25 01:18:05 -07:00
public function postCreate ()
{
$consumable = new Consumable ();
$consumable -> name = e ( Input :: get ( 'name' ));
$consumable -> category_id = e ( Input :: get ( 'category_id' ));
$consumable -> location_id = e ( Input :: get ( 'location_id' ));
$consumable -> company_id = Company :: getIdForCurrentUser ( Input :: get ( 'company_id' ));
$consumable -> order_number = e ( Input :: get ( 'order_number' ));
2016-03-25 15:24:12 -07:00
$consumable -> min_amt = e ( Input :: get ( 'min_amt' ));
2016-05-16 17:11:31 -07:00
$consumable -> manufacturer_id = e ( Input :: get ( 'manufacturer_id' ));
$consumable -> model_no = e ( Input :: get ( 'model_no' ));
$consumable -> item_no = e ( Input :: get ( 'item_no' ));
2016-03-25 01:18:05 -07:00
if ( e ( Input :: get ( 'purchase_date' )) == '' ) {
$consumable -> purchase_date = null ;
} else {
$consumable -> purchase_date = e ( Input :: get ( 'purchase_date' ));
}
if ( e ( Input :: get ( 'purchase_cost' )) == '0.00' ) {
$consumable -> purchase_cost = null ;
} else {
2016-03-25 15:24:12 -07:00
$consumable -> purchase_cost = e ( Input :: get ( 'purchase_cost' ));
2016-03-25 01:18:05 -07:00
}
$consumable -> qty = e ( Input :: get ( 'qty' ));
$consumable -> user_id = Auth :: user () -> id ;
// Was the consumable created?
if ( $consumable -> save ()) {
// Redirect to the new consumable page
2016-04-28 21:06:41 -07:00
return redirect () -> to ( " admin/consumables " ) -> with ( 'success' , trans ( 'admin/consumables/message.create.success' ));
2016-03-25 01:18:05 -07:00
}
2016-04-28 21:06:41 -07:00
return redirect () -> back () -> withInput () -> withErrors ( $consumable -> getErrors ());
2016-03-25 01:18:05 -07:00
}
/**
2016-03-28 22:51:49 -07:00
* Returns a form view to edit a consumable .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $consumableId
* @ see ConsumablesController :: postEdit () method that stores the form data .
* @ since [ v1 . 0 ]
* @ return View
*/
2016-03-25 01:18:05 -07:00
public function getEdit ( $consumableId = null )
{
// Check if the consumable exists
if ( is_null ( $consumable = Consumable :: find ( $consumableId ))) {
// Redirect to the blogs management page
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'error' , trans ( 'admin/consumables/message.does_not_exist' ));
2016-03-25 01:18:05 -07:00
} elseif ( ! Company :: isCurrentUserHasAccess ( $consumable )) {
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'error' , trans ( 'general.insufficient_permissions' ));
2016-03-25 01:18:05 -07:00
}
2016-06-05 07:47:44 -07:00
$category_list = Helper :: categoryList ( 'consumable' );
2016-03-25 01:18:05 -07:00
$company_list = Helper :: companyList ();
$location_list = Helper :: locationsList ();
2016-05-16 17:11:31 -07:00
$manufacturer_list = Helper :: manufacturerList ();
2016-03-25 01:18:05 -07:00
return View :: make ( 'consumables/edit' , compact ( 'consumable' ))
-> with ( 'category_list' , $category_list )
-> with ( 'company_list' , $company_list )
2016-05-16 17:11:31 -07:00
-> with ( 'location_list' , $location_list )
-> with ( 'manufacturer_list' , $manufacturer_list );
2016-03-25 01:18:05 -07:00
}
/**
2016-03-28 22:51:49 -07:00
* Returns a form view to edit a consumable .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $consumableId
* @ see ConsumablesController :: getEdit () method that stores the form data .
* @ since [ v1 . 0 ]
* @ return Redirect
*/
2016-03-25 01:18:05 -07:00
public function postEdit ( $consumableId = null )
{
if ( is_null ( $consumable = Consumable :: find ( $consumableId ))) {
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'error' , trans ( 'admin/consumables/message.does_not_exist' ));
2016-03-25 01:18:05 -07:00
} elseif ( ! Company :: isCurrentUserHasAccess ( $consumable )) {
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'error' , trans ( 'general.insufficient_permissions' ));
2016-03-25 01:18:05 -07:00
}
$consumable -> name = e ( Input :: get ( 'name' ));
$consumable -> category_id = e ( Input :: get ( 'category_id' ));
$consumable -> location_id = e ( Input :: get ( 'location_id' ));
$consumable -> company_id = Company :: getIdForCurrentUser ( Input :: get ( 'company_id' ));
$consumable -> order_number = e ( Input :: get ( 'order_number' ));
$consumable -> min_amt = e ( Input :: get ( 'min_amt' ));
2016-05-16 17:11:31 -07:00
$consumable -> manufacturer_id = e ( Input :: get ( 'manufacturer_id' ));
$consumable -> model_no = e ( Input :: get ( 'model_no' ));
$consumable -> item_no = e ( Input :: get ( 'item_no' ));
2016-03-25 01:18:05 -07:00
if ( e ( Input :: get ( 'purchase_date' )) == '' ) {
$consumable -> purchase_date = null ;
} else {
$consumable -> purchase_date = e ( Input :: get ( 'purchase_date' ));
}
if ( e ( Input :: get ( 'purchase_cost' )) == '0.00' ) {
$consumable -> purchase_cost = null ;
} else {
2016-03-25 15:24:12 -07:00
$consumable -> purchase_cost = e ( Input :: get ( 'purchase_cost' ));
2016-03-25 01:18:05 -07:00
}
$consumable -> qty = e ( Input :: get ( 'qty' ));
if ( $consumable -> save ()) {
2016-04-28 21:06:41 -07:00
return redirect () -> to ( " admin/consumables " ) -> with ( 'success' , trans ( 'admin/consumables/message.update.success' ));
2016-03-25 01:18:05 -07:00
}
2016-04-28 21:06:41 -07:00
return redirect () -> back () -> withInput () -> withErrors ( $consumable -> getErrors ());
2016-03-25 01:18:05 -07:00
}
/**
2016-03-28 22:51:49 -07:00
* Delete a consumable .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $consumableId
* @ since [ v1 . 0 ]
* @ return Redirect
*/
2016-03-25 01:18:05 -07:00
public function getDelete ( $consumableId )
{
// Check if the blog post exists
if ( is_null ( $consumable = Consumable :: find ( $consumableId ))) {
// Redirect to the blogs management page
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'error' , trans ( 'admin/consumables/message.not_found' ));
2016-03-25 01:18:05 -07:00
} elseif ( ! Company :: isCurrentUserHasAccess ( $consumable )) {
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'error' , trans ( 'general.insufficient_permissions' ));
2016-03-25 01:18:05 -07:00
}
$consumable -> delete ();
// Redirect to the locations management page
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'success' , trans ( 'admin/consumables/message.delete.success' ));
2016-03-25 01:18:05 -07:00
}
/**
2016-03-28 22:51:49 -07:00
* Return a view to display component information .
2016-03-25 01:18:05 -07:00
*
2016-03-28 22:51:49 -07:00
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ see ConsumablesController :: getDataView () method that generates the JSON response
* @ since [ v1 . 0 ]
* @ param int $consumableId
2016-03-25 01:18:05 -07:00
* @ return View
2016-03-28 22:51:49 -07:00
*/
public function getView ( $consumableId = null )
2016-03-25 01:18:05 -07:00
{
2016-03-28 22:51:49 -07:00
$consumable = Consumable :: find ( $consumableId );
2016-03-25 01:18:05 -07:00
if ( isset ( $consumable -> id )) {
if ( ! Company :: isCurrentUserHasAccess ( $consumable )) {
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'error' , trans ( 'general.insufficient_permissions' ));
2016-03-25 01:18:05 -07:00
} else {
return View :: make ( 'consumables/view' , compact ( 'consumable' ));
}
} else {
// Prepare the error message
2016-04-07 13:39:35 -07:00
$error = trans ( 'admin/consumables/message.does_not_exist' , compact ( 'id' ));
2016-03-25 01:18:05 -07:00
// Redirect to the user management page
2016-04-28 21:06:41 -07:00
return redirect () -> route ( 'consumables' ) -> with ( 'error' , $error );
2016-03-25 01:18:05 -07:00
}
}
/**
2016-03-28 22:51:49 -07:00
* Return a view to checkout a consumable to a user .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ see ConsumablesController :: postCheckout () method that stores the data .
* @ since [ v1 . 0 ]
* @ param int $consumableId
* @ return View
*/
2016-03-25 01:18:05 -07:00
public function getCheckout ( $consumableId )
{
// Check if the consumable exists
if ( is_null ( $consumable = Consumable :: find ( $consumableId ))) {
// Redirect to the consumable management page with error
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'consumables' ) -> with ( 'error' , trans ( 'admin/consumables/message.not_found' ));
2016-03-25 01:18:05 -07:00
} elseif ( ! Company :: isCurrentUserHasAccess ( $consumable )) {
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'error' , trans ( 'general.insufficient_permissions' ));
2016-03-25 01:18:05 -07:00
}
// Get the dropdown of users and then pass it to the checkout view
$users_list = Helper :: usersList ();
return View :: make ( 'consumables/checkout' , compact ( 'consumable' )) -> with ( 'users_list' , $users_list );
}
/**
2016-03-28 22:51:49 -07:00
* Saves the checkout information
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ see ConsumablesController :: getCheckout () method that returns the form .
* @ since [ v1 . 0 ]
* @ param int $consumableId
* @ return Redirect
*/
2016-03-25 01:18:05 -07:00
public function postCheckout ( $consumableId )
{
// Check if the consumable exists
if ( is_null ( $consumable = Consumable :: find ( $consumableId ))) {
// Redirect to the consumable management page with error
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'consumables' ) -> with ( 'error' , trans ( 'admin/consumables/message.not_found' ));
2016-03-25 01:18:05 -07:00
} elseif ( ! Company :: isCurrentUserHasAccess ( $consumable )) {
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'error' , trans ( 'general.insufficient_permissions' ));
2016-03-25 01:18:05 -07:00
}
$admin_user = Auth :: user ();
$assigned_to = e ( Input :: get ( 'assigned_to' ));
// Check if the user exists
if ( is_null ( $user = User :: find ( $assigned_to ))) {
// Redirect to the consumable management page with error
2016-04-28 21:06:41 -07:00
return redirect () -> to ( 'admin/consumables' ) -> with ( 'error' , trans ( 'admin/consumables/message.user_does_not_exist' ));
2016-03-25 01:18:05 -07:00
}
// Update the consumable data
$consumable -> assigned_to = e ( Input :: get ( 'assigned_to' ));
$consumable -> users () -> attach ( $consumable -> id , array (
'consumable_id' => $consumable -> id ,
'user_id' => $admin_user -> id ,
'assigned_to' => e ( Input :: get ( 'assigned_to' ))));
$logaction = new Actionlog ();
$logaction -> consumable_id = $consumable -> id ;
$logaction -> checkedout_to = $consumable -> assigned_to ;
$logaction -> asset_type = 'consumable' ;
2016-05-25 18:32:45 -07:00
$logaction -> asset_id = 0 ;
2016-03-25 01:18:05 -07:00
$logaction -> location_id = $user -> location_id ;
$logaction -> user_id = Auth :: user () -> id ;
$logaction -> note = e ( Input :: get ( 'note' ));
$settings = Setting :: getSettings ();
if ( $settings -> slack_endpoint ) {
$slack_settings = [
'username' => $settings -> botname ,
'channel' => $settings -> slack_channel ,
'link_names' => true
];
$client = new \Maknz\Slack\Client ( $settings -> slack_endpoint , $slack_settings );
try {
$client -> attach ([
'color' => 'good' ,
'fields' => [
[
'title' => 'Checked Out:' ,
'value' => strtoupper ( $logaction -> asset_type ) . ' <' . config ( 'app.url' ) . '/admin/consumables/' . $consumable -> id . '/view' . '|' . $consumable -> name . '> checked out to <' . config ( 'app.url' ) . '/admin/users/' . $user -> id . '/view|' . $user -> fullName () . '> by <' . config ( 'app.url' ) . '/admin/users/' . $admin_user -> id . '/view' . '|' . $admin_user -> fullName () . '>.'
],
[
'title' => 'Note:' ,
'value' => e ( $logaction -> note )
],
]
]) -> send ( 'Consumable Checked Out' );
} catch ( Exception $e ) {
}
}
$log = $logaction -> logaction ( 'checkout' );
$consumable_user = DB :: table ( 'consumables_users' ) -> where ( 'assigned_to' , '=' , $consumable -> assigned_to ) -> where ( 'consumable_id' , '=' , $consumable -> id ) -> first ();
$data [ 'log_id' ] = $logaction -> id ;
$data [ 'eula' ] = $consumable -> getEula ();
$data [ 'first_name' ] = $user -> first_name ;
$data [ 'item_name' ] = $consumable -> name ;
$data [ 'checkout_date' ] = $logaction -> created_at ;
$data [ 'note' ] = $logaction -> note ;
$data [ 'require_acceptance' ] = $consumable -> requireAcceptance ();
if (( $consumable -> requireAcceptance () == '1' ) || ( $consumable -> getEula ())) {
Mail :: send ( 'emails.accept-asset' , $data , function ( $m ) use ( $user ) {
$m -> to ( $user -> email , $user -> first_name . ' ' . $user -> last_name );
$m -> subject ( 'Confirm consumable delivery' );
});
}
// Redirect to the new consumable page
2016-04-28 21:06:41 -07:00
return redirect () -> to ( " admin/consumables " ) -> with ( 'success' , trans ( 'admin/consumables/message.checkout.success' ));
2016-03-25 01:18:05 -07:00
}
2016-03-28 22:51:49 -07:00
/**
* Returns the JSON response containing the the consumables data .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ see ConsumablesController :: getIndex () method that returns the view that consumes the JSON .
* @ since [ v1 . 0 ]
* @ param int $consumableId
* @ return View
*/
2016-03-25 01:18:05 -07:00
public function getDatatable ()
{
$consumables = Consumable :: select ( 'consumables.*' ) -> whereNull ( 'consumables.deleted_at' )
-> with ( 'company' , 'location' , 'category' , 'users' );
if ( Input :: has ( 'search' )) {
2016-03-25 15:24:12 -07:00
$consumables = $consumables -> TextSearch ( e ( Input :: get ( 'search' )));
2016-03-25 01:18:05 -07:00
}
if ( Input :: has ( 'offset' )) {
$offset = e ( Input :: get ( 'offset' ));
} else {
$offset = 0 ;
}
if ( Input :: has ( 'limit' )) {
$limit = e ( Input :: get ( 'limit' ));
} else {
$limit = 50 ;
}
2016-05-16 17:11:31 -07:00
$allowed_columns = [ 'id' , 'name' , 'order_number' , 'min_amt' , 'purchase_date' , 'purchase_cost' , 'companyName' , 'category' , 'model_no' , 'item_no' , 'manufacturer' ];
2016-03-25 01:18:05 -07:00
$order = Input :: get ( 'order' ) === 'asc' ? 'asc' : 'desc' ;
$sort = in_array ( Input :: get ( 'sort' ), $allowed_columns ) ? Input :: get ( 'sort' ) : 'created_at' ;
switch ( $sort ) {
case 'category' :
$consumables = $consumables -> OrderCategory ( $order );
break ;
case 'location' :
$consumables = $consumables -> OrderLocation ( $order );
break ;
2016-05-16 17:11:31 -07:00
case 'manufacturer' :
$consumables = $consumables -> OrderManufacturer ( $order );
break ;
2016-03-25 01:18:05 -07:00
case 'companyName' :
$consumables = $consumables -> OrderCompany ( $order );
break ;
default :
$consumables = $consumables -> orderBy ( $sort , $order );
break ;
}
$consumCount = $consumables -> count ();
$consumables = $consumables -> skip ( $offset ) -> take ( $limit ) -> get ();
$rows = array ();
foreach ( $consumables as $consumable ) {
2016-04-07 13:39:35 -07:00
$actions = '<nobr><a href="' . route ( 'checkout/consumable' , $consumable -> id ) . '" style="margin-right:5px;" class="btn btn-info btn-sm" ' . (( $consumable -> numRemaining () > 0 ) ? '' : ' disabled' ) . '>' . trans ( 'general.checkout' ) . '</a><a href="' . route ( 'update/consumable' , $consumable -> id ) . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route ( 'delete/consumable' , $consumable -> id ) . '" data-content="' . trans ( 'admin/consumables/message.delete.confirm' ) . '" data-title="' . trans ( 'general.delete' ) . ' ' . htmlspecialchars ( $consumable -> name ) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></nobr>' ;
2016-03-25 18:29:45 -07:00
$company = $consumable -> company ;
2016-03-25 01:18:05 -07:00
$rows [] = array (
'id' => $consumable -> id ,
2016-03-25 15:24:12 -07:00
'name' => ( string ) link_to ( 'admin/consumables/' . $consumable -> id . '/view' , e ( $consumable -> name )),
2016-03-25 01:18:05 -07:00
'location' => ( $consumable -> location ) ? e ( $consumable -> location -> name ) : '' ,
2016-03-25 15:24:12 -07:00
'min_amt' => e ( $consumable -> min_amt ),
'qty' => e ( $consumable -> qty ),
2016-05-16 17:11:31 -07:00
'manufacturer' => ( $consumable -> manufacturer ) ? e ( $consumable -> manufacturer -> name ) : '' ,
'model_no' => e ( $consumable -> model_no ),
'item_no' => e ( $consumable -> item_no ),
2016-03-25 15:24:12 -07:00
'category' => ( $consumable -> category ) ? e ( $consumable -> category -> name ) : 'Missing category' ,
'order_number' => e ( $consumable -> order_number ),
'purchase_date' => e ( $consumable -> purchase_date ),
2016-03-25 01:18:05 -07:00
'purchase_cost' => ( $consumable -> purchase_cost != '' ) ? number_format ( $consumable -> purchase_cost , 2 ) : '' ,
'numRemaining' => $consumable -> numRemaining (),
'actions' => $actions ,
'companyName' => is_null ( $company ) ? '' : e ( $company -> name ),
);
}
$data = array ( 'total' => $consumCount , 'rows' => $rows );
return $data ;
}
2016-03-28 22:51:49 -07:00
/**
* Returns a JSON response containing details on the users associated with this consumable .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ see ConsumablesController :: getView () method that returns the form .
* @ since [ v1 . 0 ]
* @ param int $consumableId
* @ return View
*/
public function getDataView ( $consumableId )
2016-03-25 01:18:05 -07:00
{
//$consumable = Consumable::find($consumableID);
$consumable = Consumable :: with ( array ( 'consumableAssigments' =>
function ( $query ) {
$query -> orderBy ( 'created_at' , 'DESC' );
},
'consumableAssigments.admin' => function ( $query ) {
},
'consumableAssigments.user' => function ( $query ) {
},
2016-03-28 22:51:49 -07:00
)) -> find ( $consumableId );
2016-03-25 01:18:05 -07:00
// $consumable->load('consumableAssigments.admin','consumableAssigments.user');
if ( ! Company :: isCurrentUserHasAccess ( $consumable )) {
return [ 'total' => 0 , 'rows' => []];
}
$rows = array ();
foreach ( $consumable -> consumableAssigments as $consumable_assignment ) {
$rows [] = array (
2016-03-25 15:24:12 -07:00
'name' => ( string ) link_to ( '/admin/users/' . $consumable_assignment -> user -> id . '/view' , e ( $consumable_assignment -> user -> fullName ())),
2016-03-25 01:18:05 -07:00
'created_at' => ( $consumable_assignment -> created_at -> format ( 'Y-m-d H:i:s' ) == '-0001-11-30 00:00:00' ) ? '' : $consumable_assignment -> created_at -> format ( 'Y-m-d H:i:s' ),
2016-03-25 15:24:12 -07:00
'admin' => ( $consumable_assignment -> admin ) ? e ( $consumable_assignment -> admin -> fullName ()) : '' ,
2016-03-25 01:18:05 -07:00
);
}
$consumableCount = $consumable -> users -> count ();
$data = array ( 'total' => $consumableCount , 'rows' => $rows );
return $data ;
}
}