Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions app/Http/Controllers/Api/ReportsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

use App\Http\Controllers\Controller;
use App\Http\Transformers\ActionlogsTransformer;
use App\Http\Transformers\ExpiringItemsTransformer;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\License;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

Expand Down Expand Up @@ -100,4 +103,31 @@ public function index(Request $request): JsonResponse|array

return response()->json((new ActionlogsTransformer)->transformActionlogs($actionlogs, $total), 200, ['Content-Type' => 'application/json;charset=utf8'], JSON_UNESCAPED_UNICODE);
}

public function expiringAssetsReport(Request $request)
{
$this->authorize('reports.view');
$days = $request->input('days', 30);
$assets = Asset::getExpiringWarrantyOrEol($days);

return response()->json(
(new ExpiringItemsTransformer)->transformAssets($assets, $assets->count())
);
}

public function expiringLicensesReport(Request $request)
{
$this->authorize('reports.view');

$days = (int)$request->input('days', 30);
$includeExpired = $request->boolean('include_expired', false);

$licenses = License::query()
->expiringLicenses($days, $includeExpired)
->get();

return response()->json(
(new ExpiringItemsTransformer)->transformLicenses($licenses, $licenses->count())
);
}
}
17 changes: 17 additions & 0 deletions app/Http/Controllers/ReportsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,23 @@ public function getDeprecationReport(): View
return view('reports/depreciation')->with('depreciations', $depreciations);
}

public function getExpiringItemsReport(): View
{
$this->authorize('reports.view');
$settings = Setting::getSettings();
$alert_interval = $settings->alert_interval;
$assets_count = Asset::getExpiringWarrantyOrEol($alert_interval)->count();

$licenses_count = License::query()
->expiringLicenses($alert_interval)
->with(['manufacturer', 'category'])
->orderBy('expiration_date', 'ASC')
->orderBy('termination_date', 'ASC')
->count();

return view('reports.expiring_items', compact('assets_count', 'licenses_count'));
}

/**
* Exports the depreciations to CSV
*
Expand Down
53 changes: 53 additions & 0 deletions app/Http/Transformers/ExpiringItemsTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace App\Http\Transformers;

use App\Helpers\Helper;
use Carbon\Carbon;

class ExpiringItemsTransformer
{
public function transformAssets($assets, $total)
{
$rows = [];

foreach ($assets as $asset) {
$rows[] = [
'id' => $asset->id,
'asset_tag' => $asset->asset_tag,
'model' => $asset->model->name ?? '',
'model_number' => $asset->model->model_number ?? '',
'purchase_date' => Helper::getFormattedDateObject($asset->purchase_date, 'date'),
'eol_rate' => (($asset->asset_eol_date != '') && ($asset->purchase_date != '')) ? (int)Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date, true) . ' months' : null,
'eol_date' => Helper::getFormattedDateObject($asset->eol_date, 'date'),
'warranty_expires' => $asset->warranty_expires ? $asset->warranty_expires_formatted_date .' ('.$asset->warranty_expires_diff_for_humans.')' : '',
];
}

return [
'total' => $total,
'rows' => $rows,
];
}

public function transformLicenses($licenses, $total)
{
$rows = [];

foreach ($licenses as $license) {

$rows[] = [
'id' => $license->id,
'name' => $license->name,
'purchase_date' => $license->purchase_date_formatted ?? null,
'expiration' => $license->expires_formatted_date ? $license->expires_formatted_date . ($license->expires_diff_for_humans ? ' ('.$license->expires_diff_for_humans.')' : '') : null,
'termination_date' => $license->terminates_formatted_date ? $license->terminates_formatted_date . ($license->terminates_diff_for_humans ? ' ('.$license->terminates_diff_for_humans.')' : '') : null,
];
}

return [
'total' => $total,
'rows' => $rows,
];
}
}
29 changes: 16 additions & 13 deletions app/Models/License.php
Original file line number Diff line number Diff line change
Expand Up @@ -884,25 +884,28 @@ public function scopeExpiredLicenses($query)
*/
public function scopeExpiringLicenses($query, $days = 60, $includeExpired = false)
{
return $query// The termination date is null or within range
->where(function ($query) use ($days) {
$query->whereNull('termination_date')
->orWhereBetween('termination_date', [Carbon::now(), Carbon::now()->addDays($days)]);
})
->where(function ($query) use ($days, $includeExpired) {
$now = now()->startOfDay();
$end = now()->copy()->addDays($days)->endOfDay();

return $query // The termination date is null or within range
->where(function ($query) use ($now, $end) {
$query->whereNull('termination_date')
->orWhereBetween('termination_date', [$now, $end]);
})
->where(function ($query) use ($now, $end, $includeExpired) {
$query->whereNotNull('expiration_date')
// Handle expiring licenses without termination dates
->where(function ($query) use ($days, $includeExpired) {
->where(function ($query) use ($now, $end, $includeExpired) {
$query->whereNull('termination_date')
->whereBetween('expiration_date', [Carbon::now(), Carbon::now()->addDays($days)])
// include expired licenses if requested
->when($includeExpired, function ($query) {
$query->orwhereDate('expiration_date', '<=', Carbon::now());
->whereBetween('expiration_date', [$now, $end])
//include expired licenses if requested
->when($includeExpired, function ($query) use ($now, $end) {
$query->orwhereDate('expiration_date', '<=', $now);
});
})
// Handle expiring licenses with termination dates in the future
->orWhere(function ($query) use ($days) {
$query->whereBetween('termination_date', [Carbon::now(), Carbon::now()->addDays($days)]);
->orWhere(function ($query) use ($now, $end) {
$query->whereBetween('termination_date', [$now, $end]);
});
});
}
Expand Down
157 changes: 157 additions & 0 deletions app/Presenters/ExpiringItemsPresenter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<?php

namespace App\Presenters;

/**
* Class ExpiringAssetsLicensesReportPresenter
*
* @package App\Presenters
*/
class ExpiringItemsPresenter extends Presenter
{
/**
* JSON column layout for expiring assets table.
*
* @return string
*/
public static function assetsDataTableLayout()
{
$layout = [
[
'field' => 'id',
'searchable' => true,
'sortable' => true,
'title' => trans('general.id'),
'visible' => true,
],
[
'field' => 'asset_tag',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/hardware/form.tag'),
'visible' => true,
],
[
'field' => 'model',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/hardware/form.model'),
'visible' => true,
],
[
'field' => 'model_number',
'searchable' => true,
'sortable' => true,
'title' => trans('general.model_no'),
'visible' => true,
],
[
'field' => 'purchase_date',
'searchable' => true,
'sortable' => true,
'title' => trans('general.purchase_date'),
'visible' => true,
'formatter' => 'dateDisplayFormatter',
],
[
'field' => 'eol_rate',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/hardware/form.eol_rate'),
'visible' => true,
],
[
'field' => 'eol_date',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/hardware/form.eol_date'),
'visible' => true,
'formatter' => 'dateDisplayFormatter',
],
[
'field' => 'warranty_expires',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/hardware/form.warranty_expires'),
'visible' => true,
],
];

return json_encode($layout);
}

/**
* JSON column layout for expiring licenses table.
*
* @return string
*/
public static function licensesDataTableLayout()
{
$layout = [
[
'field' => 'id',
'searchable' => true,
'sortable' => true,
'title' => trans('general.id'),
'visible' => true,
],
[
'field' => 'name',
'searchable' => true,
'sortable' => true,
'title' => trans('general.name'),
'visible' => true,
],
[
'field' => 'purchase_date',
'searchable' => true,
'sortable' => true,
'title' => trans('general.purchase_date'),
'visible' => true,
],
[
'field' => 'expiration',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/licenses/form.expiration'),
'visible' => true,
],
[
'field' => 'termination_date',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/licenses/form.termination_date'),
'visible' => true,
],
];

return json_encode($layout);
}

/**
* Combined report payload.
*
* @param array $assets
* @param array $licenses
* @param int $days
* @param bool $includeExpired
* @return array
*/
public static function reportData(array $assets, array $licenses, int $days, bool $includeExpired)
{
return [
'assets' => $assets,
'licenses' => $licenses,
'meta' => [
'days' => $days,
'include_expired' => $includeExpired,
'asset_count' => count($assets),
'license_count' => count($licenses),
],
'table_layouts' => [
'assets' => json_decode(self::assetsDataTableLayout(), true),
'licenses' => json_decode(self::licensesDataTableLayout(), true),
],
];
}
}
1 change: 1 addition & 0 deletions resources/lang/en-US/general.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
'exclude_archived' => 'Exclude Archived Assets',
'exclude_deleted' => 'Exclude Deleted Assets',
'example' => 'Example: ',
'Expiring_Items_Report' => "Expiring Items Report",
'files' => 'Files',
'file_name' => 'File Name',
'file_type' => 'File Type',
Expand Down
5 changes: 5 additions & 0 deletions resources/views/layouts/default.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -1719,6 +1719,11 @@
{{ trans('general.depreciation_report') }}
</a>
</li>
<li {{!! (request()->is('reports/expiring-items') ? ' class="active"' : '') !!}}>
<a href="{{ url('reports/expiring-items') }}">
{{ trans('general.Expiring_Items_Report') }}
</a>
</li>
<li {{!! (request()->is('reports/licenses') ? ' class="active"' : '') !!}}>
<a href="{{ url('reports/licenses') }}">
{{ trans('general.license_report') }}
Expand Down
Loading
Loading