2016-03-25 01:18:05 -07:00
< ? php
2021-06-10 13:15:52 -07:00
2018-07-24 19:35:26 -07:00
namespace App\Http\Controllers\Assets ;
2016-03-25 01:18:05 -07:00
2024-09-11 08:43:33 -07:00
use App\Events\CheckoutableCheckedIn ;
2016-03-25 01:18:05 -07:00
use App\Helpers\Helper ;
2018-07-24 19:35:26 -07:00
use App\Http\Controllers\Controller ;
2018-09-29 21:33:52 -07:00
use App\Http\Requests\ImageUploadRequest ;
2016-03-25 01:18:05 -07:00
use App\Models\Actionlog ;
2024-05-15 07:43:38 -07:00
use App\Http\Requests\UploadFileRequest ;
2023-07-13 20:48:51 -07:00
use Illuminate\Support\Facades\Log ;
2016-03-25 01:18:05 -07:00
use App\Models\Asset ;
use App\Models\AssetModel ;
2019-03-13 20:12:03 -07:00
use App\Models\CheckoutRequest ;
2016-03-25 01:18:05 -07:00
use App\Models\Company ;
use App\Models\Location ;
use App\Models\Setting ;
2023-05-15 11:52:57 -07:00
use App\Models\Statuslabel ;
2016-03-25 01:18:05 -07:00
use App\Models\User ;
2023-07-13 20:48:51 -07:00
use Illuminate\Support\Facades\Auth ;
2022-11-01 05:02:12 -07:00
use App\View\Label ;
2016-12-19 11:04:28 -08:00
use Carbon\Carbon ;
2023-07-13 20:48:51 -07:00
use Illuminate\Support\Facades\DB ;
2023-03-18 11:58:09 -07:00
use Illuminate\Support\Facades\Gate ;
2016-12-19 11:04:28 -08:00
use Illuminate\Http\Request ;
2023-07-13 20:48:51 -07:00
use Illuminate\Support\Facades\Crypt ;
2019-03-13 20:12:03 -07:00
use Illuminate\Support\Facades\Storage ;
2023-07-13 20:48:51 -07:00
use Illuminate\Support\Facades\Validator ;
2016-12-19 11:04:28 -08:00
use League\Csv\Reader ;
2024-07-04 16:54:50 -07:00
use Illuminate\Http\Response ;
use Illuminate\Contracts\View\View ;
use Illuminate\Http\RedirectResponse ;
2024-07-08 14:02:11 -07:00
use Symfony\Component\HttpFoundation\BinaryFileResponse ;
2016-03-25 01:18:05 -07:00
/**
2016-04-07 13:21:09 -07:00
* This class controls all actions related to assets for
* the Snipe - IT Asset Management application .
*
* @ version v1 . 0
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
2016-03-25 01:18:05 -07:00
*/
class AssetsController extends Controller
{
2021-06-10 13:15:52 -07:00
protected $qrCodeDimensions = [ 'height' => 3.5 , 'width' => 3.5 ];
protected $barCodeDimensions = [ 'height' => 2 , 'width' => 22 ];
2016-03-25 01:18:05 -07:00
public function __construct ()
{
$this -> middleware ( 'auth' );
parent :: __construct ();
}
/**
2018-07-16 20:09:53 -07:00
* Returns a view that invokes the ajax tables which actually contains
* the content for the assets listing , which is generated in getDatatable .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ see AssetController :: getDatatable () method that generates the JSON response
* @ since [ v1 . 0 ]
2018-07-24 19:35:26 -07:00
* @ param Request $request
2018-07-16 20:09:53 -07:00
*/
2024-07-04 16:54:50 -07:00
public function index ( Request $request ) : View
2016-03-25 01:18:05 -07:00
{
2016-12-19 11:04:28 -08:00
$this -> authorize ( 'index' , Asset :: class );
2020-05-23 11:58:44 -07:00
$company = Company :: find ( $request -> input ( 'company_id' ));
2021-06-10 13:15:52 -07:00
2017-10-01 12:57:04 -07:00
return view ( 'hardware/index' ) -> with ( 'company' , $company );
2016-03-25 01:18:05 -07:00
}
/**
2016-12-19 22:00:50 -08:00
* Returns a view that presents a form to create a new asset .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v1 . 0 ]
2016-12-29 08:10:52 -08:00
* @ param Request $request
* @ internal param int $model_id
2016-12-19 22:00:50 -08:00
*/
2024-07-04 16:54:50 -07:00
public function create ( Request $request ) : View
2016-03-25 01:18:05 -07:00
{
2016-12-19 11:04:28 -08:00
$this -> authorize ( 'create' , Asset :: class );
2024-07-04 16:54:50 -07:00
$view = view ( 'hardware/edit' )
2016-12-29 08:10:52 -08:00
-> with ( 'statuslabel_list' , Helper :: statusLabelList ())
-> with ( 'item' , new Asset )
2017-10-26 21:50:27 -07:00
-> with ( 'statuslabel_types' , Helper :: statusTypeList ());
2016-03-25 01:18:05 -07:00
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'model_id' )) {
2016-12-22 17:08:42 -08:00
$selected_model = AssetModel :: find ( $request -> input ( 'model_id' ));
2016-03-25 01:18:05 -07:00
$view -> with ( 'selected_model' , $selected_model );
}
2021-06-10 13:15:52 -07:00
2016-03-25 01:18:05 -07:00
return $view ;
}
/**
2018-07-16 20:09:53 -07:00
* Validate and process new asset form data .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v1 . 0 ]
*/
2024-07-04 16:54:50 -07:00
public function store ( ImageUploadRequest $request ) : RedirectResponse
2016-03-25 01:18:05 -07:00
{
2016-12-19 11:04:28 -08:00
$this -> authorize ( Asset :: class );
2017-10-26 21:50:27 -07:00
2024-03-12 12:00:10 -07:00
// There are a lot more rules to add here but prevents
// errors around `asset_tags` not being present below.
$this -> validate ( $request , [ 'asset_tags' => [ 'required' , 'array' ]]);
2018-10-05 04:34:47 -07:00
// Handle asset tags - there could be one, or potentially many.
// This is only necessary on create, not update, since bulk editing is handled
// differently
$asset_tags = $request -> input ( 'asset_tags' );
2017-10-26 21:50:27 -07:00
2020-06-16 16:06:25 -07:00
$settings = Setting :: getSettings ();
2018-10-05 04:34:47 -07:00
$success = false ;
2018-10-05 05:30:13 -07:00
$serials = $request -> input ( 'serials' );
2016-03-25 01:18:05 -07:00
2018-10-05 04:34:47 -07:00
for ( $a = 1 ; $a <= count ( $asset_tags ); $a ++ ) {
$asset = new Asset ();
$asset -> model () -> associate ( AssetModel :: find ( $request -> input ( 'model_id' )));
2021-06-10 13:15:52 -07:00
$asset -> name = $request -> input ( 'name' );
2020-04-21 03:58:31 -07:00
2018-10-05 05:30:13 -07:00
// Check for a corresponding serial
if (( $serials ) && ( array_key_exists ( $a , $serials ))) {
2021-06-10 13:15:52 -07:00
$asset -> serial = $serials [ $a ];
2016-07-10 18:43:00 -07:00
}
2019-08-14 23:13:23 -07:00
if (( $asset_tags ) && ( array_key_exists ( $a , $asset_tags ))) {
2021-06-10 13:15:52 -07:00
$asset -> asset_tag = $asset_tags [ $a ];
2016-07-10 18:43:00 -07:00
}
2016-03-25 01:18:05 -07:00
2018-10-05 04:34:47 -07:00
$asset -> company_id = Company :: getIdForCurrentUser ( $request -> input ( 'company_id' ));
$asset -> model_id = $request -> input ( 'model_id' );
$asset -> order_number = $request -> input ( 'order_number' );
$asset -> notes = $request -> input ( 'notes' );
2024-09-17 14:16:41 -07:00
$asset -> created_by = auth () -> id ();
2022-03-19 16:11:42 -07:00
$asset -> status_id = request ( 'status_id' );
2018-10-05 04:34:47 -07:00
$asset -> warranty_months = request ( 'warranty_months' , null );
2023-04-25 23:39:32 -07:00
$asset -> purchase_cost = request ( 'purchase_cost' );
2018-10-05 04:34:47 -07:00
$asset -> purchase_date = request ( 'purchase_date' , null );
2023-10-22 09:11:19 -07:00
$asset -> asset_eol_date = request ( 'asset_eol_date' , null );
2018-10-05 04:34:47 -07:00
$asset -> assigned_to = request ( 'assigned_to' , null );
2022-03-19 16:11:42 -07:00
$asset -> supplier_id = request ( 'supplier_id' , null );
2018-10-05 04:34:47 -07:00
$asset -> requestable = request ( 'requestable' , 0 );
$asset -> rtd_location_id = request ( 'rtd_location_id' , null );
2023-01-18 13:03:51 -08:00
$asset -> byod = request ( 'byod' , 0 );
2021-06-10 13:15:52 -07:00
if ( ! empty ( $settings -> audit_interval )) {
$asset -> next_audit_date = Carbon :: now () -> addMonths ( $settings -> audit_interval ) -> toDateString ();
2019-09-03 10:58:51 -07:00
}
2024-01-29 18:44:26 -08:00
// Set location_id to rtd_location_id ONLY if the asset isn't being checked out
if ( ! request ( 'assigned_user' ) && ! request ( 'assigned_asset' ) && ! request ( 'assigned_location' )) {
2018-10-05 04:34:47 -07:00
$asset -> location_id = $request -> input ( 'rtd_location_id' , null );
}
2017-11-03 19:41:26 -07:00
2020-04-21 03:58:31 -07:00
// Create the image (if one was chosen.)
if ( $request -> has ( 'image' )) {
$asset = $request -> handleImages ( $asset );
}
2016-03-25 01:18:05 -07:00
2020-04-21 03:58:31 -07:00
// Update custom fields in the database.
// Validation for these fields is handled through the AssetRequest form request
$model = AssetModel :: find ( $request -> get ( 'model_id' ));
2017-01-25 18:38:20 -08:00
2020-04-21 03:58:31 -07:00
if (( $model ) && ( $model -> fieldset )) {
foreach ( $model -> fieldset -> fields as $field ) {
2021-06-10 13:15:52 -07:00
if ( $field -> field_encrypted == '1' ) {
2024-08-22 06:58:09 -07:00
if ( Gate :: allows ( 'assets.view.encrypted_custom_fields' )) {
2022-06-27 14:17:07 -07:00
if ( is_array ( $request -> input ( $field -> db_column ))) {
2023-07-13 20:48:51 -07:00
$asset -> { $field -> db_column } = Crypt :: encrypt ( implode ( ', ' , $request -> input ( $field -> db_column )));
2021-06-10 13:15:52 -07:00
} else {
2023-07-13 20:48:51 -07:00
$asset -> { $field -> db_column } = Crypt :: encrypt ( $request -> input ( $field -> db_column ));
2021-06-10 13:15:52 -07:00
}
}
2020-04-21 03:58:31 -07:00
} else {
2022-06-27 14:17:07 -07:00
if ( is_array ( $request -> input ( $field -> db_column ))) {
$asset -> { $field -> db_column } = implode ( ', ' , $request -> input ( $field -> db_column ));
2021-06-10 13:15:52 -07:00
} else {
2022-06-27 14:17:07 -07:00
$asset -> { $field -> db_column } = $request -> input ( $field -> db_column );
2021-02-16 17:20:29 -08:00
}
2017-07-08 17:04:24 -07:00
}
}
2016-06-10 16:36:46 -07:00
}
2018-10-11 17:15:09 -07:00
// Validate the asset before saving
if ( $asset -> isValid () && $asset -> save ()) {
2018-10-05 04:34:47 -07:00
if ( request ( 'assigned_user' )) {
$target = User :: find ( request ( 'assigned_user' ));
$location = $target -> location_id ;
} elseif ( request ( 'assigned_asset' )) {
$target = Asset :: find ( request ( 'assigned_asset' ));
$location = $target -> location_id ;
} elseif ( request ( 'assigned_location' )) {
$target = Location :: find ( request ( 'assigned_location' ));
$location = $target -> id ;
}
2017-12-12 03:39:55 -08:00
2018-10-05 04:34:47 -07:00
if ( isset ( $target )) {
2024-07-04 12:49:22 -07:00
$asset -> checkOut ( $target , auth () -> user (), date ( 'Y-m-d H:i:s' ), $request -> input ( 'expected_checkin' , null ), 'Checked out on asset creation' , $request -> get ( 'name' ), $location );
2018-10-05 04:34:47 -07:00
}
2017-12-12 03:39:55 -08:00
2018-10-05 04:34:47 -07:00
$success = true ;
2022-05-31 21:54:05 -07:00
2016-12-29 08:10:52 -08:00
}
2018-10-05 04:34:47 -07:00
}
2024-07-25 13:35:13 -07:00
session () -> put ([ 'redirect_option' => $request -> get ( 'redirect_option' ), 'checkout_to_type' => $request -> get ( 'checkout_to_type' )]);
2024-07-25 14:02:34 -07:00
2018-10-05 04:34:47 -07:00
if ( $success ) {
2024-07-25 14:02:34 -07:00
return redirect () -> to ( Helper :: getRedirectOption ( $request , $asset -> id , 'Assets' ))
2024-07-23 08:37:01 -07:00
-> with ( 'success-unescaped' , trans ( 'admin/hardware/message.create.success_linked' , [ 'link' => route ( 'hardware.show' , [ 'hardware' => $asset -> id ]), 'id' , 'tag' => e ( $asset -> asset_tag )]));
2022-05-31 21:54:05 -07:00
2016-03-25 01:18:05 -07:00
}
2018-10-05 04:34:47 -07:00
2018-09-29 21:33:52 -07:00
return redirect () -> back () -> withInput () -> withErrors ( $asset -> getErrors ());
2016-03-25 01:18:05 -07:00
}
2022-05-31 21:54:05 -07:00
2016-03-25 01:18:05 -07:00
/**
2018-07-16 20:09:53 -07:00
* Returns a view that presents a form to edit an existing asset .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v1 . 0 ]
2024-07-04 12:49:22 -07:00
* @ return \Illuminate\Contracts\View\View
2018-07-16 20:09:53 -07:00
*/
2024-07-04 16:54:50 -07:00
public function edit ( $assetId = null ) : View | RedirectResponse
2016-03-25 01:18:05 -07:00
{
2021-06-10 13:15:52 -07:00
if ( ! $item = Asset :: find ( $assetId )) {
2016-12-19 11:04:28 -08:00
// Redirect to the asset management page with error
2016-12-15 20:02:47 -08:00
return redirect () -> route ( 'hardware.index' ) -> with ( 'error' , trans ( 'admin/hardware/message.does_not_exist' ));
2016-03-25 01:18:05 -07:00
}
2016-12-19 11:04:28 -08:00
//Handles company checks and permissions.
$this -> authorize ( $item );
2016-03-25 01:18:05 -07:00
2017-06-09 16:31:25 -07:00
return view ( 'hardware/edit' , compact ( 'item' ))
2017-10-01 12:57:04 -07:00
-> with ( 'statuslabel_list' , Helper :: statusLabelList ())
2017-10-28 11:17:52 -07:00
-> with ( 'statuslabel_types' , Helper :: statusTypeList ());
2016-03-25 01:18:05 -07:00
}
2022-03-16 11:02:07 -07:00
2018-07-16 17:44:03 -07:00
/**
2018-07-16 20:09:53 -07:00
* Returns a view that presents information about an asset for detail view .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v1 . 0 ]
2024-07-04 12:49:22 -07:00
* @ return \Illuminate\Contracts\View\View
2018-07-16 20:09:53 -07:00
*/
2024-07-04 16:54:50 -07:00
public function show ( $assetId = null ) : View | RedirectResponse
2018-07-16 17:44:03 -07:00
{
$asset = Asset :: withTrashed () -> find ( $assetId );
$this -> authorize ( 'view' , $asset );
$settings = Setting :: getSettings ();
if ( isset ( $asset )) {
$audit_log = Actionlog :: where ( 'action_type' , '=' , 'audit' )
-> where ( 'item_id' , '=' , $assetId )
-> where ( 'item_type' , '=' , Asset :: class )
-> orderBy ( 'created_at' , 'DESC' ) -> first ();
if ( $asset -> location ) {
$use_currency = $asset -> location -> currency ;
} else {
2021-06-10 13:15:52 -07:00
if ( $settings -> default_currency != '' ) {
2018-07-16 17:44:03 -07:00
$use_currency = $settings -> default_currency ;
} else {
$use_currency = trans ( 'general.currency' );
}
}
2021-06-10 13:15:52 -07:00
$qr_code = ( object ) [
2018-07-16 17:44:03 -07:00
'display' => $settings -> qr_code == '1' ,
2021-06-10 13:15:52 -07:00
'url' => route ( 'qr_code/hardware' , $asset -> id ),
];
2018-07-16 17:44:03 -07:00
return view ( 'hardware/view' , compact ( 'asset' , 'qr_code' , 'settings' ))
-> with ( 'use_currency' , $use_currency ) -> with ( 'audit_log' , $audit_log );
}
return redirect () -> route ( 'hardware.index' ) -> with ( 'error' , trans ( 'admin/hardware/message.does_not_exist' ));
}
2016-03-25 01:18:05 -07:00
/**
2018-07-16 20:09:53 -07:00
* Validate and process asset edit form .
*
* @ param int $assetId
2024-05-13 10:19:14 -07:00
* @ since [ v1 . 0 ]
2023-09-20 12:17:30 -07:00
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
2018-07-16 20:09:53 -07:00
*/
2024-07-04 16:54:50 -07:00
public function update ( ImageUploadRequest $request , $assetId = null ) : RedirectResponse
2016-03-25 01:18:05 -07:00
{
2024-07-25 13:35:13 -07:00
2016-03-25 01:18:05 -07:00
// Check if the asset exists
2021-06-10 13:15:52 -07:00
if ( ! $asset = Asset :: find ( $assetId )) {
2016-03-25 01:18:05 -07:00
// Redirect to the asset management page with error
2016-12-15 20:02:47 -08:00
return redirect () -> route ( 'hardware.index' ) -> with ( 'error' , trans ( 'admin/hardware/message.does_not_exist' ));
2016-03-25 01:18:05 -07:00
}
2016-12-19 11:04:28 -08:00
$this -> authorize ( $asset );
2016-03-25 01:18:05 -07:00
2016-12-26 15:17:46 -08:00
$asset -> status_id = $request -> input ( 'status_id' , null );
$asset -> warranty_months = $request -> input ( 'warranty_months' , null );
2023-03-29 00:56:34 -07:00
$asset -> purchase_cost = $request -> input ( 'purchase_cost' , null );
2024-05-15 06:21:01 -07:00
$asset -> purchase_date = $request -> input ( 'purchase_date' , null );
$asset -> next_audit_date = $request -> input ( 'next_audit_date' , null );
2023-10-22 09:11:19 -07:00
if ( $request -> filled ( 'purchase_date' ) && ! $request -> filled ( 'asset_eol_date' ) && ( $asset -> model -> eol > 0 )) {
2023-07-18 08:26:25 -07:00
$asset -> purchase_date = $request -> input ( 'purchase_date' , null );
2023-07-13 20:48:51 -07:00
$asset -> asset_eol_date = Carbon :: parse ( $request -> input ( 'purchase_date' )) -> addMonths ( $asset -> model -> eol ) -> format ( 'Y-m-d' );
2023-10-22 09:11:19 -07:00
$asset -> eol_explicit = false ;
2023-07-17 12:44:09 -07:00
} elseif ( $request -> filled ( 'asset_eol_date' )) {
2023-09-13 11:51:14 -07:00
$asset -> asset_eol_date = $request -> input ( 'asset_eol_date' , null );
$months = Carbon :: parse ( $asset -> asset_eol_date ) -> diffInMonths ( $asset -> purchase_date );
if ( $asset -> model -> eol ) {
2023-10-22 09:11:19 -07:00
if ( $months != $asset -> model -> eol > 0 ) {
2023-09-13 11:51:14 -07:00
$asset -> eol_explicit = true ;
} else {
$asset -> eol_explicit = false ;
}
} else {
$asset -> eol_explicit = true ;
}
2023-10-22 09:11:19 -07:00
} elseif ( ! $request -> filled ( 'asset_eol_date' ) && (( $asset -> model -> eol ) == 0 )) {
$asset -> asset_eol_date = null ;
$asset -> eol_explicit = false ;
2023-09-13 11:51:14 -07:00
}
2016-12-26 15:17:46 -08:00
$asset -> supplier_id = $request -> input ( 'supplier_id' , null );
2020-07-09 12:47:18 -07:00
$asset -> expected_checkin = $request -> input ( 'expected_checkin' , null );
2024-09-20 06:02:28 -07:00
$asset -> requestable = $request -> input ( 'requestable' , 0 );
2016-12-26 15:17:46 -08:00
$asset -> rtd_location_id = $request -> input ( 'rtd_location_id' , null );
2023-01-18 13:03:51 -08:00
$asset -> byod = $request -> input ( 'byod' , 0 );
2016-03-25 01:18:05 -07:00
2024-09-11 09:29:22 -07:00
$status = Statuslabel :: find ( $request -> input ( 'status_id' ));
2023-05-15 11:52:57 -07:00
2024-09-11 08:43:33 -07:00
// This is a non-deployable status label - we should check the asset back in.
2024-09-11 09:29:22 -07:00
if (( $status && $status -> getStatuslabelType () != 'deployable' ) && ( $target = $asset -> assignedTo )) {
2024-09-11 08:43:33 -07:00
$originalValues = $asset -> getRawOriginal ();
2023-05-15 11:52:57 -07:00
$asset -> assigned_to = null ;
2024-09-11 08:43:33 -07:00
$asset -> assigned_type = null ;
2024-09-11 09:04:09 -07:00
$asset -> accepted = null ;
2024-09-11 08:43:33 -07:00
event ( new CheckoutableCheckedIn ( $asset , $target , auth () -> user (), 'Checkin on asset update' , date ( 'Y-m-d H:i:s' ), $originalValues ));
2023-05-15 11:52:57 -07:00
}
2021-06-10 13:15:52 -07:00
if ( $asset -> assigned_to == '' ) {
2017-11-03 17:36:18 -07:00
$asset -> location_id = $request -> input ( 'rtd_location_id' , null );
}
2022-03-16 11:02:07 -07:00
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'image_delete' )) {
2018-04-24 02:54:54 -07:00
try {
unlink ( public_path () . '/uploads/assets/' . $asset -> image );
$asset -> image = '' ;
} catch ( \Exception $e ) {
2023-07-13 20:48:51 -07:00
Log :: info ( $e );
2018-04-24 02:54:54 -07:00
}
2016-03-25 01:18:05 -07:00
}
// Update the asset data
2024-07-26 06:27:07 -07:00
2021-06-10 13:15:52 -07:00
$serial = $request -> input ( 'serials' );
2024-07-26 06:27:07 -07:00
$asset -> serial = $request -> input ( 'serials' );
if ( is_array ( $request -> input ( 'serials' ))) {
$asset -> serial = $serial [ 1 ];
}
2021-06-10 13:15:52 -07:00
$asset -> name = $request -> input ( 'name' );
$asset -> company_id = Company :: getIdForCurrentUser ( $request -> input ( 'company_id' ));
$asset -> model_id = $request -> input ( 'model_id' );
2016-12-19 22:00:50 -08:00
$asset -> order_number = $request -> input ( 'order_number' );
2024-07-26 06:27:07 -07:00
$asset_tags = $request -> input ( 'asset_tags' );
$asset -> asset_tag = $request -> input ( 'asset_tags' );
if ( is_array ( $request -> input ( 'asset_tags' ))) {
$asset -> asset_tag = $asset_tags [ 1 ];
}
2021-06-10 13:15:52 -07:00
$asset -> notes = $request -> input ( 'notes' );
2016-03-25 01:18:05 -07:00
2018-09-29 21:33:52 -07:00
$asset = $request -> handleImages ( $asset );
2016-03-25 01:18:05 -07:00
2016-06-10 16:36:46 -07:00
// Update custom fields in the database.
// Validation for these fields is handlded through the AssetRequest form request
// FIXME: No idea why this is returning a Builder error on db_column_name.
// Need to investigate and fix. Using static method for now.
$model = AssetModel :: find ( $request -> get ( 'model_id' ));
2019-05-24 15:03:15 -07:00
if (( $model ) && ( $model -> fieldset )) {
2016-06-22 12:27:41 -07:00
foreach ( $model -> fieldset -> fields as $field ) {
2024-07-26 06:27:07 -07:00
2021-06-10 13:15:52 -07:00
if ( $field -> field_encrypted == '1' ) {
2024-08-22 06:58:09 -07:00
if ( Gate :: allows ( 'assets.view.encrypted_custom_fields' )) {
2022-06-27 14:17:07 -07:00
if ( is_array ( $request -> input ( $field -> db_column ))) {
2023-07-13 20:48:51 -07:00
$asset -> { $field -> db_column } = Crypt :: encrypt ( implode ( ', ' , $request -> input ( $field -> db_column )));
2021-06-10 13:15:52 -07:00
} else {
2023-07-13 20:48:51 -07:00
$asset -> { $field -> db_column } = Crypt :: encrypt ( $request -> input ( $field -> db_column ));
2021-02-16 17:20:29 -08:00
}
2016-08-25 20:59:54 -07:00
}
} else {
2022-06-27 14:17:07 -07:00
if ( is_array ( $request -> input ( $field -> db_column ))) {
$asset -> { $field -> db_column } = implode ( ', ' , $request -> input ( $field -> db_column ));
2021-06-10 13:15:52 -07:00
} else {
2022-06-27 14:17:07 -07:00
$asset -> { $field -> db_column } = $request -> input ( $field -> db_column );
2021-02-16 17:20:29 -08:00
}
2016-08-25 20:59:54 -07:00
}
2016-06-10 16:36:46 -07:00
}
}
2016-03-25 01:18:05 -07:00
2024-07-25 13:35:13 -07:00
session () -> put ([ 'redirect_option' => $request -> get ( 'redirect_option' ), 'checkout_to_type' => $request -> get ( 'checkout_to_type' )]);
2016-08-25 20:59:54 -07:00
2016-03-25 01:18:05 -07:00
if ( $asset -> save ()) {
2024-07-25 14:02:34 -07:00
return redirect () -> to ( Helper :: getRedirectOption ( $request , $assetId , 'Assets' ))
-> with ( 'success' , trans ( 'admin/hardware/message.update.success' ));
2016-03-25 01:18:05 -07:00
}
2018-10-05 07:30:42 -07:00
2019-12-06 11:07:13 -08:00
return redirect () -> back () -> withInput () -> withErrors ( $asset -> getErrors ());
2016-03-25 01:18:05 -07:00
}
/**
2018-07-16 20:09:53 -07:00
* Delete a given asset ( mark as deleted ) .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v1 . 0 ]
*/
2024-10-01 06:29:02 -07:00
public function destroy ( Request $request , $assetId ) : RedirectResponse
2016-03-25 01:18:05 -07:00
{
// Check if the asset exists
if ( is_null ( $asset = Asset :: find ( $assetId ))) {
// Redirect to the asset management page with error
2016-12-15 20:02:47 -08:00
return redirect () -> route ( 'hardware.index' ) -> with ( 'error' , trans ( 'admin/hardware/message.does_not_exist' ));
2016-03-25 01:18:05 -07:00
}
2016-12-19 11:04:28 -08:00
$this -> authorize ( 'delete' , $asset );
2024-10-01 06:29:02 -07:00
if ( $asset -> assignedTo ) {
$target = $asset -> assignedTo ;
$checkin_at = date ( 'Y-m-d H:i:s' );
$originalValues = $asset -> getRawOriginal ();
event ( new CheckoutableCheckedIn ( $asset , $target , auth () -> user (), 'Checkin on delete' , $checkin_at , $originalValues ));
DB :: table ( 'assets' )
-> where ( 'id' , $asset -> id )
-> update ([ 'assigned_to' => null ]);
}
2016-03-25 01:18:05 -07:00
2018-09-29 21:33:52 -07:00
if ( $asset -> image ) {
2021-06-10 13:15:52 -07:00
try {
2018-09-29 21:33:52 -07:00
Storage :: disk ( 'public' ) -> delete ( 'assets' . '/' . $asset -> image );
} catch ( \Exception $e ) {
2023-07-13 20:48:51 -07:00
Log :: debug ( $e );
2018-09-29 21:33:52 -07:00
}
}
2016-03-25 01:18:05 -07:00
$asset -> delete ();
2016-12-15 20:02:47 -08:00
return redirect () -> route ( 'hardware.index' ) -> with ( 'success' , trans ( 'admin/hardware/message.delete.success' ));
2016-03-25 01:18:05 -07:00
}
2022-03-16 11:02:07 -07:00
/**
* Searches the assets table by serial , and redirects if it finds one
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v3 . 0 ]
*/
2024-07-04 16:54:50 -07:00
public function getAssetBySerial ( Request $request ) : RedirectResponse
2022-03-16 11:02:07 -07:00
{
$topsearch = ( $request -> get ( 'topsearch' ) == " true " );
if ( ! $asset = Asset :: where ( 'serial' , '=' , $request -> get ( 'serial' )) -> first ()) {
return redirect () -> route ( 'hardware.index' ) -> with ( 'error' , trans ( 'admin/hardware/message.does_not_exist' ));
}
$this -> authorize ( 'view' , $asset );
return redirect () -> route ( 'hardware.show' , $asset -> id ) -> with ( 'topsearch' , $topsearch );
}
2016-03-25 01:18:05 -07:00
/**
2020-04-21 03:58:31 -07:00
* Searches the assets table by asset tag , and redirects if it finds one
2016-12-26 15:19:04 -08:00
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
2018-07-16 17:44:03 -07:00
* @ since [ v3 . 0 ]
2024-05-29 10:01:40 -07:00
* @ return \Illuminate\Http\RedirectResponse
2016-12-26 15:19:04 -08:00
*/
2024-07-04 16:54:50 -07:00
public function getAssetByTag ( Request $request , $tag = null ) : RedirectResponse
2016-03-25 01:18:05 -07:00
{
2022-11-01 05:02:12 -07:00
$tag = $tag ? $tag : $request -> get ( 'assetTag' );
2021-06-10 13:15:52 -07:00
$topsearch = ( $request -> get ( 'topsearch' ) == 'true' );
2016-03-25 01:18:05 -07:00
2024-08-05 05:26:29 -07:00
// Search for an exact and unique asset tag match
$assets = Asset :: where ( 'asset_tag' , '=' , $tag );
// If not a unique result, redirect to the index view
if ( $assets -> count () != 1 ) {
2024-08-05 06:44:26 -07:00
return redirect () -> route ( 'hardware.index' )
-> with ( 'search' , $tag )
-> with ( 'warning' , trans ( 'admin/hardware/message.does_not_exist_var' , [ 'asset_tag' => $tag ]));
2016-03-25 01:18:05 -07:00
}
2024-08-05 05:26:29 -07:00
$asset = $assets -> first ();
2016-12-19 11:04:28 -08:00
$this -> authorize ( 'view' , $asset );
2021-06-10 13:15:52 -07:00
2018-07-16 17:44:03 -07:00
return redirect () -> route ( 'hardware.show' , $asset -> id ) -> with ( 'topsearch' , $topsearch );
2016-03-25 01:18:05 -07:00
}
2021-06-10 13:15:52 -07:00
2022-03-16 11:02:07 -07:00
2016-03-25 01:18:05 -07:00
/**
2018-07-16 20:09:53 -07:00
* Return a QR code for the asset
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v1 . 0 ]
*/
2024-07-16 08:09:08 -07:00
public function getQrCode ( $assetId = null ) : Response | BinaryFileResponse | string | bool
2016-03-25 01:18:05 -07:00
{
$settings = Setting :: getSettings ();
if ( $settings -> qr_code == '1' ) {
2017-10-17 16:21:50 -07:00
$asset = Asset :: withTrashed () -> find ( $assetId );
2017-11-08 01:04:14 -08:00
if ( $asset ) {
$size = Helper :: barcodeDimensions ( $settings -> barcode_type );
$qr_file = public_path () . '/uploads/barcodes/qr-' . str_slug ( $asset -> asset_tag ) . '-' . str_slug ( $asset -> id ) . '.png' ;
if ( isset ( $asset -> id , $asset -> asset_tag )) {
if ( file_exists ( $qr_file )) {
$header = [ 'Content-type' => 'image/png' ];
2021-06-10 13:15:52 -07:00
2017-11-08 01:04:14 -08:00
return response () -> file ( $qr_file , $header );
} else {
$barcode = new \Com\Tecnick\Barcode\Barcode ();
2021-06-10 13:15:52 -07:00
$barcode_obj = $barcode -> getBarcodeObj ( $settings -> barcode_type , route ( 'hardware.show' , $asset -> id ), $size [ 'height' ], $size [ 'width' ], 'black' , [ - 2 , - 2 , - 2 , - 2 ]);
2017-11-08 01:04:14 -08:00
file_put_contents ( $qr_file , $barcode_obj -> getPngData ());
2021-06-10 13:15:52 -07:00
2017-11-08 01:04:14 -08:00
return response ( $barcode_obj -> getPngData ()) -> header ( 'Content-type' , 'image/png' );
}
2016-08-01 22:56:28 -07:00
}
2016-03-25 01:18:05 -07:00
}
2021-06-10 13:15:52 -07:00
2017-11-08 01:04:14 -08:00
return 'That asset is invalid' ;
2016-03-25 01:18:05 -07:00
}
2024-07-16 08:09:08 -07:00
return false ;
2016-03-25 01:18:05 -07:00
}
2016-05-19 19:12:42 -07:00
/**
* Return a 2 D barcode for the asset
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v1 . 0 ]
* @ return Response
*/
public function getBarCode ( $assetId = null )
{
$settings = Setting :: getSettings ();
2024-02-09 13:08:07 -08:00
if ( $asset = Asset :: withTrashed () -> find ( $assetId )) {
$barcode_file = public_path () . '/uploads/barcodes/' . str_slug ( $settings -> alt_barcode ) . '-' . str_slug ( $asset -> asset_tag ) . '.png' ;
2016-05-19 19:12:42 -07:00
2024-02-09 13:08:07 -08:00
if ( isset ( $asset -> id , $asset -> asset_tag )) {
if ( file_exists ( $barcode_file )) {
$header = [ 'Content-type' => 'image/png' ];
2021-06-10 13:15:52 -07:00
2024-02-09 13:08:07 -08:00
return response () -> file ( $barcode_file , $header );
} else {
// Calculate barcode width in pixel based on label width (inch)
$barcode_width = ( $settings -> labels_width - $settings -> labels_display_sgutter ) * 200.000000000001 ;
2017-10-19 06:08:01 -07:00
2024-02-09 13:08:07 -08:00
$barcode = new \Com\Tecnick\Barcode\Barcode ();
try {
$barcode_obj = $barcode -> getBarcodeObj ( $settings -> alt_barcode , $asset -> asset_tag , ( $barcode_width < 300 ? $barcode_width : 300 ), 50 );
file_put_contents ( $barcode_file , $barcode_obj -> getPngData ());
2021-06-10 13:15:52 -07:00
2024-02-09 13:08:07 -08:00
return response ( $barcode_obj -> getPngData ()) -> header ( 'Content-type' , 'image/png' );
} catch ( \Exception $e ) {
Log :: debug ( 'The barcode format is invalid.' );
2021-06-10 13:15:52 -07:00
2024-02-09 13:08:07 -08:00
return response ( file_get_contents ( public_path ( 'uploads/barcodes/invalid_barcode.gif' ))) -> header ( 'Content-type' , 'image/gif' );
}
2021-03-17 22:19:10 -07:00
}
2016-08-01 22:56:28 -07:00
}
2016-05-19 19:12:42 -07:00
}
2024-02-09 13:08:07 -08:00
return null ;
2016-05-19 19:12:42 -07:00
}
2020-02-04 18:15:01 -08:00
2019-09-03 11:02:55 -07:00
/**
* Return a label for an individual asset .
*
* @ author [ L . Swartzendruber ] [ < logan . swartzendruber @ gmail . com >
* @ param int $assetId
2024-07-04 12:49:22 -07:00
* @ return \Illuminate\Contracts\View\View
2019-09-03 11:02:55 -07:00
*/
2020-04-21 03:58:31 -07:00
public function getLabel ( $assetId = null )
2019-09-03 11:02:55 -07:00
{
if ( isset ( $assetId )) {
$asset = Asset :: find ( $assetId );
2020-04-21 03:58:31 -07:00
$this -> authorize ( 'view' , $asset );
2019-09-03 11:02:55 -07:00
2022-11-01 05:02:12 -07:00
return ( new Label ())
2022-10-26 17:12:42 -07:00
-> with ( 'assets' , collect ([ $asset ]))
2019-09-03 11:02:55 -07:00
-> with ( 'settings' , Setting :: getSettings ())
2022-11-02 01:04:40 -07:00
-> with ( 'template' , request () -> get ( 'template' ))
2022-11-01 05:02:12 -07:00
-> with ( 'offset' , request () -> get ( 'offset' ))
2020-04-21 03:58:31 -07:00
-> with ( 'bulkedit' , false )
-> with ( 'count' , 0 );
2016-05-19 19:12:42 -07:00
}
}
2016-03-25 01:18:05 -07:00
/**
2018-07-16 20:09:53 -07:00
* Returns a view that presents a form to clone an asset .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v1 . 0 ]
2024-07-04 12:49:22 -07:00
* @ return \Illuminate\Contracts\View\View
2018-07-16 20:09:53 -07:00
*/
2024-07-24 09:49:38 -07:00
public function getClone ( Asset $asset )
2016-03-25 01:18:05 -07:00
{
2024-07-24 09:49:38 -07:00
$this -> authorize ( 'create' , $asset );
$cloned = clone $asset ;
$cloned -> id = null ;
$cloned -> asset_tag = '' ;
$cloned -> serial = '' ;
$cloned -> assigned_to = '' ;
$cloned -> deleted_at = '' ;
2016-03-25 01:18:05 -07:00
2017-06-09 16:31:25 -07:00
return view ( 'hardware/edit' )
2018-07-16 20:09:53 -07:00
-> with ( 'statuslabel_list' , Helper :: statusLabelList ())
-> with ( 'statuslabel_types' , Helper :: statusTypeList ())
2024-07-24 09:49:38 -07:00
-> with ( 'item' , $cloned );
2016-03-25 01:18:05 -07:00
}
2016-08-12 16:01:59 -07:00
/**
* Return history import view
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v1 . 0 ]
2024-07-04 12:49:22 -07:00
* @ return \Illuminate\Contracts\View\View
2016-08-12 16:01:59 -07:00
*/
public function getImportHistory ()
{
2019-02-08 16:05:56 -08:00
$this -> authorize ( 'admin' );
2021-06-10 13:15:52 -07:00
2017-06-09 16:31:25 -07:00
return view ( 'hardware/history' );
2016-08-12 16:01:59 -07:00
}
/**
* Import history
*
* This needs a LOT of love . It ' s done very inelegantly right now , and there are
* a ton of optimizations that could ( and should ) be done .
2021-06-10 13:15:52 -07:00
*
2021-04-20 21:25:17 -07:00
* Updated to respect checkin dates :
* No checkin column , assume all items are checked in ( todays date )
* Checkin date in the past , update history .
* Checkin date in future or empty , check the item out to the user .
2021-06-10 13:15:52 -07:00
*
2016-08-12 16:01:59 -07:00
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v3 . 3 ]
2024-07-04 12:49:22 -07:00
* @ return \Illuminate\Contracts\View\View
2016-08-12 16:01:59 -07:00
*/
public function postImportHistory ( Request $request )
{
2021-06-10 13:15:52 -07:00
if ( ! $request -> hasFile ( 'user_import_csv' )) {
2019-08-13 18:00:21 -07:00
return back () -> with ( 'error' , 'No file provided. Please select a file for import and try again. ' );
}
2021-06-10 13:15:52 -07:00
if ( ! ini_get ( 'auto_detect_line_endings' )) {
ini_set ( 'auto_detect_line_endings' , '1' );
2016-08-12 16:01:59 -07:00
}
2020-09-03 11:42:33 -07:00
$csv = Reader :: createFromPath ( $request -> file ( 'user_import_csv' ));
2019-08-13 18:00:21 -07:00
$csv -> setHeaderOffset ( 0 );
2021-04-20 21:25:17 -07:00
$header = $csv -> getHeader ();
2021-06-10 13:15:52 -07:00
$isCheckinHeaderExplicit = in_array ( 'checkin date' , ( array_map ( 'strtolower' , $header )));
2023-03-14 14:07:09 -07:00
try {
$results = $csv -> getRecords ();
} catch ( \Exception $e ) {
2023-03-21 23:56:07 -07:00
return back () -> with ( 'error' , trans ( 'general.error_in_import_file' , [ 'error' => $e -> getMessage ()]));
2023-03-14 14:07:09 -07:00
}
2021-06-10 13:15:52 -07:00
$item = [];
$status = [];
$status [ 'error' ] = [];
$status [ 'success' ] = [];
2016-12-29 14:02:18 -08:00
foreach ( $results as $row ) {
2016-08-12 16:01:59 -07:00
if ( is_array ( $row )) {
$row = array_change_key_case ( $row , CASE_LOWER );
2021-06-10 13:15:52 -07:00
$asset_tag = Helper :: array_smart_fetch ( $row , 'asset tag' );
if ( ! array_key_exists ( $asset_tag , $item )) {
$item [ $asset_tag ] = [];
2016-08-12 16:01:59 -07:00
}
$batch_counter = count ( $item [ $asset_tag ]);
2021-06-10 13:15:52 -07:00
$item [ $asset_tag ][ $batch_counter ][ 'checkout_date' ] = Carbon :: parse ( Helper :: array_smart_fetch ( $row , 'checkout date' )) -> format ( 'Y-m-d H:i:s' );
if ( $isCheckinHeaderExplicit ) {
2021-04-20 21:25:17 -07:00
//checkin date not empty, assume past transaction or future checkin date (expected)
2021-06-10 13:15:52 -07:00
if ( ! empty ( Helper :: array_smart_fetch ( $row , 'checkin date' ))) {
$item [ $asset_tag ][ $batch_counter ][ 'checkin_date' ] = Carbon :: parse ( Helper :: array_smart_fetch ( $row , 'checkin date' )) -> format ( 'Y-m-d H:i:s' );
2021-04-20 21:25:17 -07:00
} else {
$item [ $asset_tag ][ $batch_counter ][ 'checkin_date' ] = '' ;
}
} else {
//checkin header missing, assume data is unavailable and make checkin date explicit (now) so we don't encounter invalid state.
$item [ $asset_tag ][ $batch_counter ][ 'checkin_date' ] = Carbon :: parse ( now ()) -> format ( 'Y-m-d H:i:s' );
}
2021-06-10 13:15:52 -07:00
$item [ $asset_tag ][ $batch_counter ][ 'asset_tag' ] = Helper :: array_smart_fetch ( $row , 'asset tag' );
$item [ $asset_tag ][ $batch_counter ][ 'name' ] = Helper :: array_smart_fetch ( $row , 'name' );
$item [ $asset_tag ][ $batch_counter ][ 'email' ] = Helper :: array_smart_fetch ( $row , 'email' );
2016-12-29 14:02:18 -08:00
if ( $asset = Asset :: where ( 'asset_tag' , '=' , $asset_tag ) -> first ()) {
2016-09-20 09:22:49 -07:00
$item [ $asset_tag ][ $batch_counter ][ 'asset_id' ] = $asset -> id ;
2016-12-29 14:02:18 -08:00
$base_username = User :: generateFormattedNameFromFullName ( Setting :: getSettings () -> username_format , $item [ $asset_tag ][ $batch_counter ][ 'name' ]);
$user = User :: where ( 'username' , '=' , $base_username [ 'username' ]);
2016-09-20 09:22:49 -07:00
$user_query = ' on username ' . $base_username [ 'username' ];
2021-06-10 13:15:52 -07:00
if ( $request -> input ( 'match_firstnamelastname' ) == '1' ) {
2016-12-29 14:02:18 -08:00
$firstnamedotlastname = User :: generateFormattedNameFromFullName ( 'firstname.lastname' , $item [ $asset_tag ][ $batch_counter ][ 'name' ]);
2016-09-20 09:22:49 -07:00
$item [ $asset_tag ][ $batch_counter ][ 'username' ][] = $firstnamedotlastname [ 'username' ];
2016-12-29 14:02:18 -08:00
$user -> orWhere ( 'username' , '=' , $firstnamedotlastname [ 'username' ]);
2016-09-20 09:22:49 -07:00
$user_query .= ', or on username ' . $firstnamedotlastname [ 'username' ];
2016-08-12 16:01:59 -07:00
}
2021-06-10 13:15:52 -07:00
if ( $request -> input ( 'match_flastname' ) == '1' ) {
2016-12-29 14:02:18 -08:00
$flastname = User :: generateFormattedNameFromFullName ( 'filastname' , $item [ $asset_tag ][ $batch_counter ][ 'name' ]);
2016-09-20 09:22:49 -07:00
$item [ $asset_tag ][ $batch_counter ][ 'username' ][] = $flastname [ 'username' ];
2016-12-29 14:02:18 -08:00
$user -> orWhere ( 'username' , '=' , $flastname [ 'username' ]);
2016-09-20 09:22:49 -07:00
$user_query .= ', or on username ' . $flastname [ 'username' ];
}
2021-06-10 13:15:52 -07:00
if ( $request -> input ( 'match_firstname' ) == '1' ) {
2016-12-29 14:02:18 -08:00
$firstname = User :: generateFormattedNameFromFullName ( 'firstname' , $item [ $asset_tag ][ $batch_counter ][ 'name' ]);
2016-09-20 09:22:49 -07:00
$item [ $asset_tag ][ $batch_counter ][ 'username' ][] = $firstname [ 'username' ];
2016-12-29 14:02:18 -08:00
$user -> orWhere ( 'username' , '=' , $firstname [ 'username' ]);
2016-09-20 09:22:49 -07:00
$user_query .= ', or on username ' . $firstname [ 'username' ];
}
2021-06-10 13:15:52 -07:00
if ( $request -> input ( 'match_email' ) == '1' ) {
if ( $item [ $asset_tag ][ $batch_counter ][ 'name' ] == '' ) {
2016-09-20 09:22:49 -07:00
$item [ $asset_tag ][ $batch_counter ][ 'username' ][] = $user_email = User :: generateEmailFromFullName ( $item [ $asset_tag ][ $batch_counter ][ 'name' ]);
2016-12-29 14:02:18 -08:00
$user -> orWhere ( 'username' , '=' , $user_email );
2016-09-20 09:22:49 -07:00
$user_query .= ', or on username ' . $user_email ;
}
}
2021-06-10 13:15:52 -07:00
if ( $request -> input ( 'match_username' ) == '1' ) {
2021-04-20 21:25:17 -07:00
// Added #8825: add explicit username lookup
2021-06-10 13:15:52 -07:00
$raw_username = $item [ $asset_tag ][ $batch_counter ][ 'name' ];
$user -> orWhere ( 'username' , '=' , $raw_username );
$user_query .= ', or on username ' . $raw_username ;
2021-04-20 21:25:17 -07:00
}
2016-09-20 09:22:49 -07:00
// A matching user was found
if ( $user = $user -> first ()) {
2021-04-20 21:25:17 -07:00
//$user is now matched user from db
2016-08-12 16:01:59 -07:00
$item [ $asset_tag ][ $batch_counter ][ 'user_id' ] = $user -> id ;
2021-04-20 21:25:17 -07:00
2021-06-10 13:15:52 -07:00
Actionlog :: firstOrCreate ([
2018-07-16 20:09:53 -07:00
'item_id' => $asset -> id ,
'item_type' => Asset :: class ,
2024-09-17 14:16:41 -07:00
'created_by' => auth () -> id (),
2024-07-04 12:49:22 -07:00
'note' => 'Checkout imported by ' . auth () -> user () -> present () -> fullName () . ' from history importer' ,
2018-07-16 20:09:53 -07:00
'target_id' => $item [ $asset_tag ][ $batch_counter ][ 'user_id' ],
'target_type' => User :: class ,
'created_at' => $item [ $asset_tag ][ $batch_counter ][ 'checkout_date' ],
'action_type' => 'checkout' ,
2021-06-10 13:15:52 -07:00
]);
2021-04-20 21:25:17 -07:00
$checkin_date = $item [ $asset_tag ][ $batch_counter ][ 'checkin_date' ];
if ( $isCheckinHeaderExplicit ) {
2024-02-23 03:40:10 -08:00
// if checkin date header exists, assume that empty or future date is still checked out
// if checkin is before today's date, assume it's checked in and do not assign user ID, if checkin date is in the future or blank, this is the expected checkin date, items are checked out
2021-06-10 13:15:52 -07:00
2024-02-23 03:40:10 -08:00
if (( strtotime ( $checkin_date ) > strtotime ( Carbon :: now ())) || ( empty ( $checkin_date )))
{
2021-04-20 21:25:17 -07:00
//only do this if item is checked out
$asset -> assigned_to = $user -> id ;
$asset -> assigned_type = User :: class ;
}
}
2021-06-10 13:15:52 -07:00
if ( ! empty ( $checkin_date )) {
2021-04-20 21:25:17 -07:00
//only make a checkin there is a valid checkin date or we created one on import.
2021-06-10 13:15:52 -07:00
Actionlog :: firstOrCreate ([
'item_id' => $item [ $asset_tag ][ $batch_counter ][ 'asset_id' ],
2021-04-20 21:25:17 -07:00
'item_type' => Asset :: class ,
2024-09-17 14:16:41 -07:00
'created_by' => auth () -> id (),
2024-07-04 12:49:22 -07:00
'note' => 'Checkin imported by ' . auth () -> user () -> present () -> fullName () . ' from history importer' ,
2021-04-20 21:25:17 -07:00
'target_id' => null ,
'created_at' => $checkin_date ,
2021-06-10 13:15:52 -07:00
'action_type' => 'checkin' ,
]);
2021-04-20 21:25:17 -07:00
}
2021-06-10 13:15:52 -07:00
2016-09-20 09:22:49 -07:00
if ( $asset -> save ()) {
2021-06-10 13:15:52 -07:00
$status [ 'success' ][][ 'asset' ][ $asset_tag ][ 'msg' ] = 'Asset successfully matched for ' . Helper :: array_smart_fetch ( $row , 'name' ) . $user_query . ' on ' . $item [ $asset_tag ][ $batch_counter ][ 'checkout_date' ];
2016-09-20 09:22:49 -07:00
} else {
$status [ 'error' ][][ 'asset' ][ $asset_tag ][ 'msg' ] = 'Asset and user was matched but could not be saved.' ;
}
2016-08-12 16:01:59 -07:00
} else {
2021-04-20 21:25:17 -07:00
$item [ $asset_tag ][ $batch_counter ][ 'user_id' ] = null ;
2021-06-10 13:15:52 -07:00
$status [ 'error' ][][ 'user' ][ Helper :: array_smart_fetch ( $row , 'name' )][ 'msg' ] = 'User does not exist so no checkin log was created.' ;
2016-08-12 16:01:59 -07:00
}
} else {
2016-09-20 09:22:49 -07:00
$item [ $asset_tag ][ $batch_counter ][ 'asset_id' ] = null ;
$status [ 'error' ][][ 'asset' ][ $asset_tag ][ 'msg' ] = 'Asset does not exist so no match was attempted.' ;
2016-08-12 16:01:59 -07:00
}
}
}
2021-06-10 13:15:52 -07:00
2017-06-09 16:31:25 -07:00
return view ( 'hardware/history' ) -> with ( 'status' , $status );
2016-08-12 16:01:59 -07:00
}
2019-08-14 22:27:17 -07:00
public function sortByName ( array $recordA , array $recordB ) : int
2019-02-08 16:05:56 -08:00
{
return strcmp ( $recordB [ 'Full Name' ], $recordA [ 'Full Name' ]);
}
2016-03-25 01:18:05 -07:00
/**
2023-04-11 10:52:14 -07:00
* Restore a deleted asset .
2018-07-16 20:09:53 -07:00
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v1 . 0 ]
2024-07-04 12:49:22 -07:00
* @ return \Illuminate\Contracts\View\View
2018-07-16 20:09:53 -07:00
*/
2016-03-25 01:18:05 -07:00
public function getRestore ( $assetId = null )
{
2023-11-22 10:02:47 -08:00
if ( $asset = Asset :: withTrashed () -> find ( $assetId )) {
$this -> authorize ( 'delete' , $asset );
if ( $asset -> deleted_at == '' ) {
return redirect () -> back () -> with ( 'error' , trans ( 'general.not_deleted' , [ 'item_type' => trans ( 'general.asset' )]));
}
if ( $asset -> restore ()) {
// Redirect them to the deleted page if there are more, otherwise the section index
$deleted_assets = Asset :: onlyTrashed () -> count ();
if ( $deleted_assets > 0 ) {
2023-11-22 10:14:44 -08:00
return redirect () -> back () -> with ( 'success' , trans ( 'admin/hardware/message.restore.success' ));
2023-11-22 10:02:47 -08:00
}
return redirect () -> route ( 'hardware.index' ) -> with ( 'success' , trans ( 'admin/hardware/message.restore.success' ));
}
// Check validation to make sure we're not restoring an asset with the same asset tag (or unique attribute) as an existing asset
return redirect () -> back () -> with ( 'error' , trans ( 'general.could_not_restore' , [ 'item_type' => trans ( 'general.asset' ), 'error' => $asset -> getErrors () -> first ()]));
2016-03-25 01:18:05 -07:00
}
2021-06-10 13:15:52 -07:00
2016-12-19 22:00:50 -08:00
return redirect () -> route ( 'hardware.index' ) -> with ( 'error' , trans ( 'admin/hardware/message.does_not_exist' ));
2016-03-25 01:18:05 -07:00
}
2017-10-28 11:17:52 -07:00
public function quickScan ()
2017-08-29 16:00:22 -07:00
{
$this -> authorize ( 'audit' , Asset :: class );
$dt = Carbon :: now () -> addMonths ( 12 ) -> toDateString ();
2021-06-10 13:15:52 -07:00
2024-08-15 02:17:08 -07:00
return view ( 'hardware/quickscan' ) -> with ( 'next_audit_date' , $dt );
2017-08-29 16:00:22 -07:00
}
2016-08-25 21:03:24 -07:00
2021-12-19 13:53:31 -08:00
public function quickScanCheckin ()
{
$this -> authorize ( 'checkin' , Asset :: class );
2024-08-15 02:08:48 -07:00
return view ( 'hardware/quickscan-checkin' ) -> with ( 'statusLabel_list' , Helper :: statusLabelList ());
2021-12-19 13:53:31 -08:00
}
2017-10-27 17:38:11 -07:00
public function audit ( $id )
2017-08-25 10:04:19 -07:00
{
2017-11-21 20:13:51 -08:00
$settings = Setting :: getSettings ();
2017-08-25 10:04:19 -07:00
$this -> authorize ( 'audit' , Asset :: class );
2017-11-21 20:13:51 -08:00
$dt = Carbon :: now () -> addMonths ( $settings -> audit_interval ) -> toDateString ();
2017-08-25 10:04:19 -07:00
$asset = Asset :: findOrFail ( $id );
2021-06-10 13:15:52 -07:00
2017-10-28 11:17:52 -07:00
return view ( 'hardware/audit' ) -> with ( 'asset' , $asset ) -> with ( 'next_audit_date' , $dt ) -> with ( 'locations_list' );
2017-08-25 10:04:19 -07:00
}
2016-08-18 12:44:55 -07:00
2019-05-05 19:32:52 -07:00
public function dueForAudit ()
{
$this -> authorize ( 'audit' , Asset :: class );
2021-06-10 13:15:52 -07:00
2019-05-05 19:32:52 -07:00
return view ( 'hardware/audit-due' );
}
2024-04-26 11:01:26 -07:00
public function dueForCheckin ()
2019-05-05 19:32:52 -07:00
{
2024-04-26 11:01:26 -07:00
$this -> authorize ( 'checkin' , Asset :: class );
2021-06-10 13:15:52 -07:00
2024-04-26 11:01:26 -07:00
return view ( 'hardware/checkin-due' );
2019-05-05 19:32:52 -07:00
}
2022-03-16 11:02:07 -07:00
2024-05-15 07:43:38 -07:00
public function auditStore ( UploadFileRequest $request , $id )
2017-08-25 10:04:19 -07:00
{
$this -> authorize ( 'audit' , Asset :: class );
2016-09-27 14:56:05 -07:00
2021-06-10 13:15:52 -07:00
$rules = [
2017-08-25 18:40:20 -07:00
'location_id' => 'exists:locations,id|nullable|numeric' ,
2021-06-10 13:15:52 -07:00
'next_audit_date' => 'date|nullable' ,
];
2016-09-27 14:56:05 -07:00
2023-07-13 20:48:51 -07:00
$validator = Validator :: make ( $request -> all (), $rules );
2018-04-24 02:54:54 -07:00
2017-08-25 18:40:20 -07:00
if ( $validator -> fails ()) {
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , $validator -> errors () -> all ()));
2016-03-25 01:18:05 -07:00
}
2017-08-25 10:04:19 -07:00
$asset = Asset :: findOrFail ( $id );
2018-04-24 02:54:54 -07:00
2024-05-15 09:38:42 -07:00
/**
2024-05-15 09:52:50 -07:00
* Even though we do a save () further down , we don ' t want to log this as a " normal " asset update ,
* which would trigger the Asset Observer and would log an asset * update * log entry ( because the
* de - normed fields like next_audit_date on the asset itself will change on save ()) * in addition * to
* the audit log entry we ' re creating through this controller .
2024-05-15 09:38:42 -07:00
*
2024-05-15 09:52:50 -07:00
* To prevent this double - logging ( one for update and one for audit ), we skip the observer and bypass
* that de - normed update log entry by using unsetEventDispatcher (), BUT invoking unsetEventDispatcher ()
* will bypass normal model - level validation that ' s usually handled at the observer )
*
* We handle validation on the save () by checking if the asset is valid via the -> isValid () method ,
2024-05-15 09:38:42 -07:00
* which manually invokes Watson Validating to make sure the asset ' s model is valid .
*
* @ see \App\Observers\AssetObserver :: updating ()
*/
2017-12-12 02:32:45 -08:00
$asset -> unsetEventDispatcher ();
2017-08-25 10:04:19 -07:00
$asset -> next_audit_date = $request -> input ( 'next_audit_date' );
2021-04-30 15:37:39 -07:00
$asset -> last_audit_date = date ( 'Y-m-d H:i:s' );
2016-03-25 01:18:05 -07:00
2018-09-07 05:39:41 -07:00
// Check to see if they checked the box to update the physical location,
// not just note it in the audit notes
2021-06-10 13:15:52 -07:00
if ( $request -> input ( 'update_location' ) == '1' ) {
2018-09-07 05:39:41 -07:00
$asset -> location_id = $request -> input ( 'location_id' );
}
2024-07-08 05:19:05 -07:00
2022-03-16 11:02:07 -07:00
2024-05-15 09:38:42 -07:00
/**
* Invoke Watson Validating to check the asset itself and check to make sure it saved correctly .
* We have to invoke this manually because of the unsetEventDispatcher () above . )
*/
2024-05-15 06:21:01 -07:00
if ( $asset -> isValid () && $asset -> save ()) {
2024-05-16 11:56:58 -07:00
$file_name = null ;
2024-05-15 07:43:38 -07:00
// Create the image (if one was chosen.)
2018-04-24 02:54:54 -07:00
if ( $request -> hasFile ( 'image' )) {
2024-05-15 07:43:38 -07:00
$file_name = $request -> handleFile ( 'private_uploads/audits/' , 'audit-' . $asset -> id , $request -> file ( 'image' ));
2018-04-24 02:54:54 -07:00
}
2018-09-29 21:33:52 -07:00
$asset -> logAudit ( $request -> input ( 'note' ), $request -> input ( 'location_id' ), $file_name );
2022-03-21 07:27:18 -07:00
return redirect () -> route ( 'assets.audit.due' ) -> with ( 'success' , trans ( 'admin/hardware/message.audit.success' ));
2017-08-25 10:04:19 -07:00
}
2024-05-15 06:21:01 -07:00
return redirect () -> back () -> withInput () -> withErrors ( $asset -> getErrors ());
2016-03-25 01:18:05 -07:00
}
2017-11-02 04:21:57 -07:00
2018-04-04 17:33:02 -07:00
public function getRequestedIndex ( $user_id = null )
2017-11-02 04:21:57 -07:00
{
2022-04-28 07:45:37 -07:00
$this -> authorize ( 'index' , Asset :: class );
2018-04-04 17:33:02 -07:00
$requestedItems = CheckoutRequest :: with ( 'user' , 'requestedItem' ) -> whereNull ( 'canceled_at' ) -> with ( 'user' , 'requestedItem' );
if ( $user_id ) {
$requestedItems -> where ( 'user_id' , $user_id ) -> get ();
2017-11-02 04:21:57 -07:00
}
2018-04-04 17:33:02 -07:00
$requestedItems = $requestedItems -> orderBy ( 'created_at' , 'desc' ) -> get ();
2017-11-02 04:21:57 -07:00
return view ( 'hardware/requested' , compact ( 'requestedItems' ));
}
2020-04-28 08:31:30 -07:00
}