Use PHP streaming to generate asset report to prevent timeouts

This commit is contained in:
snipe 2016-09-12 14:10:04 -07:00
parent 391c9a77ef
commit d357326dc1

View file

@ -21,6 +21,7 @@ use Illuminate\Support\Facades\View;
use Input;
use League\Csv\Reader;
use Redirect;
use Symfony\Component\HttpFoundation\StreamedResponse;
/**
* This controller handles all actions related to Reports for
@ -32,12 +33,12 @@ class ReportsController extends Controller
{
/**
* Returns a view that displaysthe accessories report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
* Returns a view that displaysthe accessories report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getAccessoryReport()
{
$accessories = Accessory::orderBy('created_at', 'DESC')->with('company')->get();
@ -46,14 +47,14 @@ class ReportsController extends Controller
}
/**
* Exports the accessories to CSV
*
* @deprecated Server-side exports have been replaced by datatables export since v2.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ManufacturersController::getDatatable() method that generates the JSON response
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
* Exports the accessories to CSV
*
* @deprecated Server-side exports have been replaced by datatables export since v2.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ManufacturersController::getDatatable() method that generates the JSON response
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
public function exportAccessoryReport()
{
$accessories = Accessory::orderBy('created_at', 'DESC')->get();
@ -88,12 +89,12 @@ class ReportsController extends Controller
}
/**
* Display asset report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
* Display asset report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getAssetsReport()
{
$settings = \App\Models\Setting::first();
@ -108,151 +109,110 @@ class ReportsController extends Controller
'model.manufacturer',
'company'
)
->orderBy('created_at', 'DESC')
->get();
->orderBy('created_at', 'DESC')
->get();
return View::make('reports/asset', compact('assets'))->with('settings', $settings);
}
/**
* Exports the assets to CSV
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
* Exports the assets to CSV
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
public function exportAssetReport()
{
// Grab all the assets
$assets = Asset::orderBy('created_at', 'DESC')->get();
$rows = [ ];
\Debugbar::disable();
// Create the header row
$header = [
trans('admin/hardware/table.asset_tag'),
trans('admin/hardware/form.manufacturer'),
trans('admin/hardware/form.model'),
trans('general.model_no'),
trans('general.name'),
trans('admin/hardware/table.serial'),
trans('general.status'),
trans('admin/hardware/table.purchase_date'),
trans('admin/hardware/table.purchase_cost'),
trans('admin/hardware/form.order'),
trans('admin/hardware/form.supplier'),
trans('admin/hardware/table.checkoutto'),
trans('admin/hardware/table.location'),
trans('general.notes'),
];
$header = array_map('trim', $header);
$rows[] = implode($header, ',');
$response = new StreamedResponse(function(){
// Open output stream
$handle = fopen('php://output', 'w');
// Create a row per asset
foreach ($assets as $asset) {
$row = [ ];
$row[] = e($asset->asset_tag);
if ($asset->model->manufacturer) {
$row[] = e($asset->model->manufacturer->name);
} else {
$row[] = '';
}
$row[] = '"' . e($asset->model->name) . '"';
$row[] = '"' . e($asset->model->modelno) . '"';
$row[] = e($asset->name);
$row[] = e($asset->serial);
if ($asset->assetstatus) {
$row[] = e($asset->assetstatus->name);
} else {
$row[] = '';
}
$row[] = $asset->purchase_date;
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
if ($asset->order_number) {
$row[] = e($asset->order_number);
} else {
$row[] = '';
}
if ($asset->supplier_id) {
$row[] = e($asset->supplier->name);
} else {
$row[] = '';
}
Asset::with('assigneduser', 'assetloc','defaultLoc','assigneduser.userloc','model','supplier','assetstatus','model.manufacturer')->orderBy('created_at', 'DESC')->chunk(500, function($assets) use($handle) {
fputcsv($handle, [
trans('admin/hardware/table.asset_tag'),
trans('admin/hardware/form.manufacturer'),
trans('admin/hardware/form.model'),
trans('general.model_no'),
trans('general.name'),
trans('admin/hardware/table.serial'),
trans('general.status'),
trans('admin/hardware/table.purchase_date'),
trans('admin/hardware/table.purchase_cost'),
trans('admin/hardware/form.order'),
trans('admin/hardware/form.supplier'),
trans('admin/hardware/table.checkoutto'),
trans('admin/hardware/table.location'),
trans('general.notes'),
]);
if ($asset->assigned_to > 0) {
$user = User::find($asset->assigned_to);
$row[] = e($user->fullName());
} else {
$row[] = ''; // Empty string if unassigned
}
if (( $asset->assigned_to > 0 ) && ( $asset->assigneduser->location_id > 0 )) {
$location = Location::find($asset->assigneduser->location_id);
if ($location) {
$row[] = e($location->name);
} else {
$row[] = '';
foreach ($assets as $asset) {
// Add a new row with data
fputcsv($handle, [
$asset->asset_tag,
($asset->model->manufacturer) ? $asset->model->manufacturer->name : '',
($asset->model) ? $asset->model->name : '',
($asset->model->modelno) ? $asset->model->modelno : '',
($asset->name) ? $asset->name : '',
($asset->serial) ? $asset->serial : '',
($asset->assetstatus) ? e($asset->assetstatus->name) : '',
($asset->purchase_date) ? e($asset->purchase_date) : '',
($asset->purchase_cost > 0) ? Helper::formatCurrencyOutput($asset->purchase_cost) : '',
($asset->order_number) ? e($asset->order_number) : '',
($asset->supplier) ? e($asset->supplier->name) : '',
($asset->assigneduser) ? e($asset->assigneduser->fullName()) : '',
($asset->assigneduser && $asset->assigneduser->userloc!='') ?
e($asset->assigneduser->userloc->name) : ( ($asset->defaultLoc!='') ? e($asset->defaultLoc->name) : ''),
($asset->notes) ? e($asset->notes) : '',
]);
}
} elseif ($asset->rtd_location_id) {
$location = Location::find($asset->rtd_location_id);
if ($location->name) {
$row[] = e($location->name);
} else {
$row[] = '';
}
} else {
$row[] = ''; // Empty string if location is not set
}
});
if ($asset->notes) {
$row[] = '"' . e($asset->notes) . '"';
} else {
$row[] = '';
}
$rows[] = implode($row, ',');
}
// spit out a csv
$csv = implode($rows, "\n");
$response = Response::make($csv, 200);
$response->header('Content-Type', 'text/csv');
$response->header('Content-disposition', 'attachment;filename=report.csv');
// Close the output stream
fclose($handle);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="assets-'.date('Y-m-d-his').'.csv"',
]);
return $response;
}
/**
* Show depreciation report for assets.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
* Show depreciation report for assets.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getDeprecationReport()
{
// Grab all the assets
$assets = Asset::with('model', 'assigneduser', 'assetstatus', 'defaultLoc', 'assetlog', 'company')
->orderBy('created_at', 'DESC')->get();
->orderBy('created_at', 'DESC')->get();
return View::make('reports/depreciation', compact('assets'));
}
/**
* Exports the depreciations to CSV
*
* @deprecated Server-side exports have been replaced by datatables export since v2.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
* Exports the depreciations to CSV
*
* @deprecated Server-side exports have been replaced by datatables export since v2.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
public function exportDeprecationReport()
{
// Grab all the assets
$assets = Asset::with('model', 'assigneduser', 'assetstatus', 'defaultLoc', 'assetlog')
->orderBy('created_at', 'DESC')->get();
->orderBy('created_at', 'DESC')->get();
$csv = \League\Csv\Writer::createFromFileObject(new \SplTempFileObject());
$csv->setOutputBOM(Reader::BOM_UTF16_BE);
@ -321,47 +281,51 @@ class ReportsController extends Controller
}
/**
* Displays activity report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
* Displays activity report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getActivityReport()
{
$log_actions = Actionlog::orderBy('created_at', 'DESC')
->with('user')
->with('item')
->get();
->with('adminlog')
->with('accessorylog')
->with('assetlog')
->with('licenselog')
->with('userlog')
->orderBy('created_at', 'DESC')
->get();
return View::make('reports/activity', compact('log_actions'));
}
/**
* Displays license report
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
* Displays license report
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getLicenseReport()
{
$licenses = License::orderBy('created_at', 'DESC')
->with('company')
->get();
->with('company')
->get();
return View::make('reports/licenses', compact('licenses'));
}
/**
* Exports the licenses to CSV
*
* @deprecated Server-side exports have been replaced by datatables export since v2.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
* Exports the licenses to CSV
*
* @deprecated Server-side exports have been replaced by datatables export since v2.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
public function exportLicenseReport()
{
$licenses = License::orderBy('created_at', 'DESC')->get();
@ -403,13 +367,13 @@ class ReportsController extends Controller
}
/**
* Returns a form that allows the user to generate a custom CSV report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ReportsController::postCustomReport() method that generates the CSV
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
* Returns a form that allows the user to generate a custom CSV report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ReportsController::postCustomReport() method that generates the CSV
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
public function getCustomReport()
{
$customfields = CustomField::get();
@ -417,13 +381,13 @@ class ReportsController extends Controller
}
/**
* Exports the custom report to CSV
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ReportsController::getCustomReport() method that generates form view
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
* Exports the custom report to CSV
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ReportsController::getCustomReport() method that generates form view
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
public function postCustom()
{
$assets = Asset::orderBy('created_at', 'DESC')->get();
@ -628,7 +592,7 @@ class ReportsController extends Controller
return $response;
} else {
return redirect()->to("reports/custom")
->with('error', trans('admin/reports/message.error'));
->with('error', trans('admin/reports/message.error'));
}
}
@ -643,8 +607,8 @@ class ReportsController extends Controller
{
// Grab all the improvements
$assetMaintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company')
->orderBy('created_at', 'DESC')
->get();
->orderBy('created_at', 'DESC')
->get();
return View::make('reports/asset_maintenances', compact('assetMaintenances'));
@ -661,8 +625,8 @@ class ReportsController extends Controller
{
// Grab all the improvements
$assetMaintenances = AssetMaintenance::with('asset', 'supplier')
->orderBy('created_at', 'DESC')
->get();
->orderBy('created_at', 'DESC')
->get();
$rows = [ ];
@ -690,7 +654,7 @@ class ReportsController extends Controller
$row[] = e($assetMaintenance->completion_date);
if (is_null($assetMaintenance->asset_maintenance_time)) {
$improvementTime = intval(Carbon::now()
->diffInDays(Carbon::parse($assetMaintenance->start_date)));
->diffInDays(Carbon::parse($assetMaintenance->start_date)));
} else {
$improvementTime = intval($assetMaintenance->asset_maintenance_time);
}
@ -734,7 +698,7 @@ class ReportsController extends Controller
// Grab all the improvements
$assetsForReport = Actionlog::whereIn('id', $this->getAssetsNotAcceptedYet())
->get();
->get();
$rows = [ ];
@ -751,11 +715,11 @@ class ReportsController extends Controller
foreach ($assetsForReport as $assetItem) {
$row = [ ];
$row[] = str_replace(',', '', e($assetItem->item->model->category->name));
$row[] = str_replace(',', '', e($assetItem->item->model->name));
$row[] = str_replace(',', '', e($assetItem->item->showAssetName()));
$row[] = str_replace(',', '', e($assetItem->item->asset_tag));
$row[] = str_replace(',', '', e($assetItem->item->assigneduser->fullName()));
$row[] = str_replace(',', '', e($assetItem->assetlog->model->category->name));
$row[] = str_replace(',', '', e($assetItem->assetlog->model->name));
$row[] = str_replace(',', '', e($assetItem->assetlog->showAssetName()));
$row[] = str_replace(',', '', e($assetItem->assetlog->asset_tag));
$row[] = str_replace(',', '', e($assetItem->assetlog->assigneduser->fullName()));
$rows[] = implode($row, ',');
}
@ -781,10 +745,10 @@ class ReportsController extends Controller
protected function getCheckedOutAssetsRequiringAcceptance($modelsInCategoriesThatRequireAcceptance)
{
$assets = Asset::deployed()
->inModelList($modelsInCategoriesThatRequireAcceptance)
->select('id')
->get()
->toArray();
->inModelList($modelsInCategoriesThatRequireAcceptance)
->select('id')
->get()
->toArray();
return array_pluck($assets, 'id');
}
@ -801,9 +765,9 @@ class ReportsController extends Controller
{
return array_pluck(Model::inCategory($assetCategoriesRequiringAcceptance)
->select('id')
->get()
->toArray(), 'id');
->select('id')
->get()
->toArray(), 'id');
}
/**
@ -817,9 +781,9 @@ class ReportsController extends Controller
{
return array_pluck(Category::requiresAcceptance()
->select('id')
->get()
->toArray(), 'id');
->select('id')
->get()
->toArray(), 'id');
}
/**