3
0
mirror of https://github.com/snipe/snipe-it.git synced 2026-02-05 12:55:46 +00:00

Merge remote-tracking branch 'origin/develop'

This commit is contained in:
snipe
2025-08-10 20:51:27 +01:00
431 changed files with 1222 additions and 1853 deletions

View File

@ -62,19 +62,19 @@ class Purge extends Command
$assetcount = $assets->count();
$this->info($assets->count().' assets purged.');
$asset_assoc = 0;
$asset_maintenances = 0;
$maintenances = 0;
foreach ($assets as $asset) {
$this->info('- Asset "'.$asset->present()->name().'" deleted.');
$asset_assoc += $asset->assetlog()->count();
$asset->assetlog()->forceDelete();
$asset_maintenances += $asset->assetmaintenances()->count();
$asset->assetmaintenances()->forceDelete();
$maintenances += $asset->maintenances()->count();
$asset->maintenances()->forceDelete();
$asset->forceDelete();
}
$this->info($asset_assoc.' corresponding log records purged.');
$this->info($asset_maintenances.' corresponding maintenance records purged.');
$this->info($maintenances.' corresponding maintenance records purged.');
$locations = Location::whereNotNull('deleted_at')->withTrashed()->get();
$this->info($locations->count().' locations purged.');

View File

@ -242,6 +242,7 @@ class RestoreFromBackup extends Command
$private_dirs = [
'storage/private_uploads/accessories',
'storage/private_uploads/maintenances',
'storage/private_uploads/assetmodels',
'storage/private_uploads/assets', // these are asset _files_, not the pictures.
'storage/private_uploads/audits',
@ -260,9 +261,9 @@ class RestoreFromBackup extends Command
];
$public_dirs = [
'public/uploads/accessories',
'public/uploads/maintenances',
'public/uploads/assets', // these are asset _pictures_, not asset files
'public/uploads/avatars',
//'public/uploads/barcodes', // we don't want this, let the barcodes be regenerated
'public/uploads/categories',
'public/uploads/companies',
'public/uploads/components',

View File

@ -1,132 +0,0 @@
<?php
namespace App\Http\Controllers\Accessories;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\Accessory;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Response;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
class AccessoriesFilesController extends Controller
{
/**
* Validates and stores files associated with a accessory.
*
* @param UploadFileRequest $request
* @param int $accessoryId
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @todo Switch to using the AssetFileRequest form request validator.
*/
public function store(UploadFileRequest $request, $accessoryId = null) : RedirectResponse
{
if (config('app.lock_passwords')) {
return redirect()->route('accessories.show', ['accessory'=>$accessoryId])->with('error', trans('general.feature_disabled'));
}
$accessory = Accessory::find($accessoryId);
if (isset($accessory->id)) {
$this->authorize('accessories.files', $accessory);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/accessories')) {
Storage::makeDirectory('private_uploads/accessories', 775);
}
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/accessories/', 'accessory-'.$accessory->id, $file);
//Log the upload to the log
$accessory->logUpload($file_name, e($request->input('notes')));
}
return redirect()->route('accessories.show', $accessory->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
}
return redirect()->route('accessories.show', $accessory->id)->withFragment('files')->with('error', trans('general.no_files_uploaded'));
}
// Prepare the error message
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
}
/**
* Deletes the selected accessory file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $accessoryId
* @param int $fileId
*/
public function destroy($accessoryId = null, $fileId = null) : RedirectResponse
{
if ($accessory = Accessory::find($accessoryId)) {
$this->authorize('update', $accessory);
if ($log = Actionlog::find($fileId)) {
if (Storage::exists('private_uploads/accessories/'.$log->filename)) {
try {
Storage::delete('private_uploads/accessories/' . $log->filename);
$log->delete();
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
} catch (\Exception $e) {
Log::debug($e);
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist'));
}
}
}
return redirect()->route('accessories.show', ['accessory' => $accessory])->withFragment('files')->with('error', trans('general.log_record_not_found'));
}
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
}
/**
* Allows the selected file to be viewed.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.4]
* @param int $accessoryId
* @param int $fileId
*/
public function show($accessoryId = null, $fileId = null) : View | RedirectResponse | Response | BinaryFileResponse | StreamedResponse
{
// the accessory is valid
if ($accessory = Accessory::find($accessoryId)) {
$this->authorize('view', $accessory);
$this->authorize('accessories.files', $accessory);
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
$file = 'private_uploads/accessories/'.$log->filename;
try {
return StorageHelper::showOrDownloadFile($file, $log->filename);
} catch (\Exception $e) {
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.file_not_found'));
}
}
return redirect()->route('accessories.show', ['accessory' => $accessory])->withFragment('files')->with('error', trans('general.log_record_not_found'));
}
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
}
}

View File

@ -5,11 +5,10 @@ namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\ImageUploadRequest;
use App\Http\Transformers\AssetMaintenancesTransformer;
use App\Http\Transformers\MaintenancesTransformer;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Maintenance;
use App\Models\Company;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
@ -19,13 +18,13 @@ use Illuminate\Http\JsonResponse;
*
* @version v2.0
*/
class AssetMaintenancesController extends Controller
class MaintenancesController extends Controller
{
/**
* Generates the JSON response for asset maintenances listing view.
*
* @see AssetMaintenancesController::getIndex() method that generates view
* @see MaintenancesController::getIndex() method that generates view
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
@ -34,7 +33,7 @@ class AssetMaintenancesController extends Controller
{
$this->authorize('view', Asset::class);
$maintenances = AssetMaintenance::select('asset_maintenances.*')
$maintenances = Maintenance::select('maintenances.*')
->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.assetstatus', 'adminuser');
if ($request->filled('search')) {
@ -46,11 +45,11 @@ class AssetMaintenancesController extends Controller
}
if ($request->filled('supplier_id')) {
$maintenances->where('asset_maintenances.supplier_id', '=', $request->input('supplier_id'));
$maintenances->where('maintenances.supplier_id', '=', $request->input('supplier_id'));
}
if ($request->filled('created_by')) {
$maintenances->where('asset_maintenances.created_by', '=', $request->input('created_by'));
$maintenances->where('maintenances.created_by', '=', $request->input('created_by'));
}
if ($request->filled('asset_maintenance_type')) {
@ -64,7 +63,7 @@ class AssetMaintenancesController extends Controller
$allowed_columns = [
'id',
'title',
'name',
'asset_maintenance_time',
'asset_maintenance_type',
'cost',
@ -113,7 +112,7 @@ class AssetMaintenancesController extends Controller
$total = $maintenances->count();
$maintenances = $maintenances->skip($offset)->take($limit)->get();
return (new AssetMaintenancesTransformer())->transformAssetMaintenances($maintenances, $total);
return (new MaintenancesTransformer())->transformMaintenances($maintenances, $total);
}
@ -122,7 +121,7 @@ class AssetMaintenancesController extends Controller
/**
* Validates and stores the new asset maintenance
*
* @see AssetMaintenancesController::getCreate() method for the form
* @see MaintenancesController::getCreate() method for the form
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
@ -132,13 +131,13 @@ class AssetMaintenancesController extends Controller
$this->authorize('update', Asset::class);
// create a new model instance
$maintenance = new AssetMaintenance();
$maintenance = new Maintenance();
$maintenance->fill($request->all());
$maintenance->created_by = auth()->id();
$maintenance = $request->handleImages($maintenance);
// Was the asset maintenance created?
if ($maintenance->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/asset_maintenances/message.create.success')));
return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/maintenances/message.create.success')));
}
@ -159,11 +158,11 @@ class AssetMaintenancesController extends Controller
{
$this->authorize('update', Asset::class);
if ($maintenance = AssetMaintenance::with('asset')->find($id)) {
if ($maintenance = Maintenance::with('asset')->find($id)) {
// Can this user manage this asset?
if (! Company::isCurrentUserHasAccess($maintenance->asset)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.action_permission_denied', ['item_type' => trans('admin/asset_maintenances/general.maintenance'), 'id' => $id, 'action' => trans('general.edit')])));
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.action_permission_denied', ['item_type' => trans('admin/maintenances/general.maintenance'), 'id' => $id, 'action' => trans('general.edit')])));
}
// The asset this miantenance is attached to is not valid or has been deleted
@ -174,13 +173,13 @@ class AssetMaintenancesController extends Controller
$maintenance->fill($request->all());
if ($maintenance->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/asset_maintenances/message.edit.success')));
return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/maintenances/message.edit.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $maintenance->getErrors()));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.item_not_found', ['item_type' => trans('admin/asset_maintenances/general.maintenance'), 'id' => $id])));
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.item_not_found', ['item_type' => trans('admin/maintenances/general.maintenance'), 'id' => $id])));
}
@ -188,20 +187,20 @@ class AssetMaintenancesController extends Controller
* Delete an asset maintenance
*
* @author A. Gianotto <snipe@snipe.net>
* @param int $assetMaintenanceId
* @param int $maintenanceId
* @version v1.0
* @since [v4.0]
*/
public function destroy($assetMaintenanceId) : JsonResponse | array
public function destroy($maintenanceId) : JsonResponse | array
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
$maintenance = Maintenance::findOrFail($maintenanceId);
$assetMaintenance->delete();
$maintenance->delete();
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.delete.success')));
return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/maintenances/message.delete.success')));
}
@ -210,19 +209,19 @@ class AssetMaintenancesController extends Controller
* View an asset maintenance
*
* @author A. Gianotto <snipe@snipe.net>
* @param int $assetMaintenanceId
* @param int $maintenanceId
* @version v1.0
* @since [v4.0]
*/
public function show($assetMaintenanceId) : JsonResponse | array
public function show($maintenanceId) : JsonResponse | array
{
$this->authorize('view', Asset::class);
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
if (! Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
$maintenance = Maintenance::findOrFail($maintenanceId);
if (! Company::isCurrentUserHasAccess($maintenance->asset)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot view a maintenance for that asset'));
}
return (new AssetMaintenancesTransformer())->transformAssetMaintenance($assetMaintenance);
return (new MaintenancesTransformer())->transformMaintenance($maintenance);
}
}

View File

@ -194,7 +194,7 @@ class SuppliersController extends Controller
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Supplier::class);
$supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->findOrFail($id);
$supplier = Supplier::with('maintenances', 'assets', 'licenses')->withCount('maintenances as maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->findOrFail($id);
$this->authorize('delete', $supplier);
@ -202,8 +202,8 @@ class SuppliersController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_assets', ['asset_count' => (int) $supplier->assets_count])));
}
if ($supplier->asset_maintenances_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_maintenances', ['asset_maintenances_count' => $supplier->asset_maintenances_count])));
if ($supplier->maintenances_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_maintenances', ['maintenances_count' => $supplier->maintenances_count])));
}
if ($supplier->licenses_count > 0) {

View File

@ -10,6 +10,7 @@ use App\Http\Transformers\UploadedFilesTransformer;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Maintenance;
use App\Models\AssetModel;
use App\Models\Component;
use App\Models\Consumable;
@ -27,9 +28,9 @@ use Symfony\Component\HttpFoundation\StreamedResponse;
class UploadedFilesController extends Controller
{
static $map_object_type = [
'accessories' => Accessory::class,
'maintenances' => Maintenance::class,
'assets' => Asset::class,
'components' => Component::class,
'consumables' => Consumable::class,
@ -42,18 +43,20 @@ class UploadedFilesController extends Controller
static $map_storage_path = [
'accessories' => 'private_uploads/accessories/',
'maintenances' => 'private_uploads/maintenances/',
'assets' => 'private_uploads/assets/',
'components' => 'private_uploads/components/',
'consumables' => 'private_uploads/consumables/',
'hardware' => 'private_uploads/assets/',
'licenses' => 'private_uploads/licenses/',
'locations' => 'private_uploads/locations/',
'models' => 'private_uploads/assetmodels/',
'models' => 'private_uploads/models/',
'users' => 'private_uploads/users/',
];
static $map_file_prefix= [
'accessories' => 'accessory',
'maintenances' => 'maintenance',
'assets' => 'asset',
'components' => 'component',
'consumables' => 'consumable',

View File

@ -20,6 +20,7 @@ use App\Models\Consumable;
use App\Models\License;
use App\Models\User;
use App\Notifications\CurrentInventory;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
@ -822,4 +823,37 @@ class UsersController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')), 200);
}
/**
* Run the LDAP sync command to import users from LDAP via API.
*
* @author A. Gianotto <snipe@snipe.net>
* @since 8.2.2
*
* @return \Illuminate\Http\JsonResponse
*/
public function syncLdapUsers(Request $request)
{
$this->authorize('update', User::class);
// Call Artisan LDAP import command.
Artisan::call('snipeit:ldap-sync', ['--location_id' => $request->input('location_id'), '--json_summary' => true]);
// Collect and parse JSON summary.
$ldap_results_json = Artisan::output();
$ldap_results = json_decode($ldap_results_json, true);
if (!$ldap_results) {
return response()->json(Helper::formatStandardApiResponse('error', null,trans('general.no_results')), 200);
}
// Direct user to appropriate status page.
if ($ldap_results['error']) {
return response()->json(Helper::formatStandardApiResponse('error', null, $ldap_results['error_message']), 200);
}
return response()->json(Helper::formatStandardApiResponse('success', null, $ldap_results['summary']), 200);
}
}

View File

@ -1,115 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Helpers\StorageHelper;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\AssetModel;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Storage;
use \Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class AssetModelsFilesController extends Controller
{
/**
* Upload a file to the server.
*
* @param UploadFileRequest $request
* @param int $modelId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*@since [v1.0]
* @author [A. Gianotto] [<snipe@snipe.net>]
*/
public function store(UploadFileRequest $request, $modelId = null) : RedirectResponse
{
if (! $model = AssetModel::find($modelId)) {
return redirect()->route('models.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
$this->authorize('update', $model);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/assetmodels')) {
Storage::makeDirectory('private_uploads/assetmodels', 775);
}
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/assetmodels/','model-'.$model->id,$file);
$model->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->withFragment('files')->with('success', trans('general.file_upload_success'));
}
return redirect()->back()->withFragment('files')->with('error', trans('admin/hardware/message.upload.nofiles'));
}
/**
* Check for permissions and display the file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $modelId
* @param int $fileId
* @since [v1.0]
*/
public function show(AssetModel $model, $fileId = null) : StreamedResponse | Response | RedirectResponse | BinaryFileResponse
{
$this->authorize('view', $model);
if (! $log = Actionlog::find($fileId)) {
return response('No matching record for that model/file', 500)
->header('Content-Type', 'text/plain');
}
$file = 'private_uploads/assetmodels/'.$log->filename;
if (! Storage::exists($file)) {
return response('File '.$file.' not found on server', 404)
->header('Content-Type', 'text/plain');
}
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
}
return StorageHelper::downloader($file);
}
/**
* Delete the associated file
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $modelId
* @param int $fileId
* @since [v1.0]
*/
public function destroy(AssetModel $model, $fileId = null) : RedirectResponse
{
$rel_path = 'private_uploads/assetmodels';
$this->authorize('update', $model);
$log = Actionlog::find($fileId);
if ($log) {
if (Storage::exists($rel_path.'/'.$log->filename)) {
Storage::delete($rel_path.'/'.$log->filename);
}
$log->delete();
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
}
}

View File

@ -1,108 +0,0 @@
<?php
namespace App\Http\Controllers\Assets;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\Asset;
use \Illuminate\Http\Response;
use Illuminate\Support\Facades\Storage;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class AssetFilesController extends Controller
{
/**
* Upload a file to the server.
*
* @param UploadFileRequest $request
* @param int $assetId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*@since [v1.0]
* @author [A. Gianotto] [<snipe@snipe.net>]
*/
public function store(UploadFileRequest $request, Asset $asset) : RedirectResponse
{
$this->authorize('update', $asset);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/assets')) {
Storage::makeDirectory('private_uploads/assets', 775);
}
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
$asset->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.upload.success'));
}
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
}
/**
* Check for permissions and display the file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @param int $fileId
* @since [v1.0]
*/
public function show(Asset $asset, $fileId = null) : View | RedirectResponse | Response | StreamedResponse | BinaryFileResponse
{
$this->authorize('view', $asset);
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
$file = 'private_uploads/assets/'.$log->filename;
if ($log->action_type == 'audit') {
$file = 'private_uploads/audits/'.$log->filename;
}
try {
return StorageHelper::showOrDownloadFile($file, $log->filename);
} catch (\Exception $e) {
return redirect()->route('hardware.show', $asset)->with('error', trans('general.file_not_found'));
}
}
return redirect()->route('hardware.show', $asset)->with('error', trans('general.log_record_not_found'));
}
/**
* Delete the associated file
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @param int $fileId
* @since [v1.0]
*/
public function destroy(Asset $asset, $fileId = null) : RedirectResponse
{
$this->authorize('update', $asset);
$rel_path = 'private_uploads/assets';
if ($log = Actionlog::find($fileId)) {
if (Storage::exists($rel_path.'/'.$log->filename)) {
Storage::delete($rel_path.'/'.$log->filename);
}
$log->delete();
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->route('hardware.show', $asset)->with('error', trans('general.log_record_not_found'));
}
}

View File

@ -1,138 +0,0 @@
<?php
namespace App\Http\Controllers\Components;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\Component;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\JsonResponse;
use Illuminate\Support\Facades\Log;
class ComponentsFilesController extends Controller
{
/**
* Validates and stores files associated with a component.
*
* @param UploadFileRequest $request
* @param int $componentId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*@author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @todo Switch to using the AssetFileRequest form request validator.
*/
public function store(UploadFileRequest $request, $componentId = null)
{
if (config('app.lock_passwords')) {
return redirect()->route('components.show', ['component'=>$componentId])->with('error', trans('general.feature_disabled'));
}
$component = Component::find($componentId);
if (isset($component->id)) {
$this->authorize('update', $component);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/components')) {
Storage::makeDirectory('private_uploads/components', 775);
}
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/components/','component-'.$component->id, $file);
//Log the upload to the log
$component->logUpload($file_name, e($request->input('notes')));
}
return redirect()->route('components.show', $component->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
}
return redirect()->route('components.show', $component->id)->with('error', trans('general.no_files_uploaded'));
}
// Prepare the error message
return redirect()->route('components.index')
->with('error', trans('general.file_does_not_exist'));
}
/**
* Deletes the selected component file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $componentId
* @param int $fileId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($componentId = null, $fileId = null)
{
$component = Component::find($componentId);
// the asset is valid
if (isset($component->id)) {
$this->authorize('update', $component);
$log = Actionlog::find($fileId);
// Remove the file if one exists
if (Storage::exists('components/'.$log->filename)) {
try {
Storage::delete('components/'.$log->filename);
} catch (\Exception $e) {
Log::debug($e);
}
}
$log->delete();
return redirect()->back()->withFragment('files')
->with('success', trans('admin/hardware/message.deletefile.success'));
}
// Redirect to the licence management page
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist'));
}
/**
* Allows the selected file to be viewed.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.4]
* @param int $componentId
* @param int $fileId
* @return \Symfony\Component\HttpFoundation\Response
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($componentId = null, $fileId = null)
{
Log::debug('Private filesystem is: '.config('filesystems.default'));
// the component is valid
if ($component = Component::find($componentId)) {
$this->authorize('view', $component);
$this->authorize('components.files', $component);
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $component->id)->find($fileId)) {
$file = 'private_uploads/components/'.$log->filename;
try {
return StorageHelper::showOrDownloadFile($file, $log->filename);
} catch (\Exception $e) {
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.file_not_found'));
}
}
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.log_record_not_found'));
}
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
}
}

View File

@ -1,134 +0,0 @@
<?php
namespace App\Http\Controllers\Consumables;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\Consumable;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Symfony\Consumable\HttpFoundation\JsonResponse;
use Illuminate\Support\Facades\Log;
class ConsumablesFilesController extends Controller
{
/**
* Validates and stores files associated with a consumable.
*
* @param UploadFileRequest $request
* @param int $consumableId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*@author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @todo Switch to using the AssetFileRequest form request validator.
*/
public function store(UploadFileRequest $request, $consumableId = null)
{
if (config('app.lock_passwords')) {
return redirect()->route('consumables.show', ['consumable'=>$consumableId])->with('error', trans('general.feature_disabled'));
}
$consumable = Consumable::find($consumableId);
if (isset($consumable->id)) {
$this->authorize('update', $consumable);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/consumables')) {
Storage::makeDirectory('private_uploads/consumables', 775);
}
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/consumables/','consumable-'.$consumable->id, $file);
//Log the upload to the log
$consumable->logUpload($file_name, e($request->input('notes')));
}
return redirect()->route('consumables.show', $consumable->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
}
return redirect()->route('consumables.show', $consumable->id)->with('error', trans('general.no_files_uploaded'));
}
// Prepare the error message
return redirect()->route('consumables.index')
->with('error', trans('general.file_does_not_exist'));
}
/**
* Deletes the selected consumable file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $consumableId
* @param int $fileId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($consumableId = null, $fileId = null)
{
$consumable = Consumable::find($consumableId);
// the asset is valid
if (isset($consumable->id)) {
$this->authorize('update', $consumable);
$log = Actionlog::find($fileId);
// Remove the file if one exists
if (Storage::exists('consumables/'.$log->filename)) {
try {
Storage::delete('consumables/'.$log->filename);
} catch (\Exception $e) {
Log::debug($e);
}
}
$log->delete();
return redirect()->back()->withFragment('files')
->with('success', trans('admin/hardware/message.deletefile.success'));
}
// Redirect to the licence management page
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist'));
}
/**
* Allows the selected file to be viewed.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.4]
* @param int $consumableId
* @param int $fileId
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($consumableId = null, $fileId = null)
{
$consumable = Consumable::find($consumableId);
// the consumable is valid
if (isset($consumable->id)) {
$this->authorize('view', $consumable);
$this->authorize('consumables.files', $consumable);
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $consumable->id)->find($fileId)) {
$file = 'private_uploads/consumables/'.$log->filename;
try {
return StorageHelper::showOrDownloadFile($file, $log->filename);
} catch (\Exception $e) {
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.file_not_found'));
}
}
// The log record doesn't exist somehow
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.log_record_not_found'));
}
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
}
}

View File

@ -1,132 +0,0 @@
<?php
namespace App\Http\Controllers\Licenses;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\License;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
class LicenseFilesController extends Controller
{
/**
* Validates and stores files associated with a license.
*
* @param UploadFileRequest $request
* @param int $licenseId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @todo Switch to using the AssetFileRequest form request validator.
*/
public function store(UploadFileRequest $request, $licenseId = null)
{
$license = License::find($licenseId);
if (isset($license->id)) {
$this->authorize('update', $license);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/licenses')) {
Storage::makeDirectory('private_uploads/licenses', 775);
}
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/licenses/','license-'.$license->id, $file);
//Log the upload to the log
$license->logUpload($file_name, e($request->input('notes')));
}
return redirect()->route('licenses.show', $license->id)->with('success', trans('admin/licenses/message.upload.success'));
}
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.nofiles'));
}
// Prepare the error message
return redirect()->route('licenses.index')
->with('error', trans('admin/licenses/message.does_not_exist'));
}
/**
* Deletes the selected license file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $licenseId
* @param int $fileId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($licenseId = null, $fileId = null)
{
if ($license = License::find($licenseId)) {
$this->authorize('update', $license);
if ($log = Actionlog::find($fileId)) {
// Remove the file if one exists
if (Storage::exists('licenses/'.$log->filename)) {
try {
Storage::delete('licenses/'.$log->filename);
} catch (\Exception $e) {
Log::debug($e);
}
}
$log->delete();
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->route('licenses.index')->with('error', trans('general.log_does_not_exist'));
}
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
}
/**
* Allows the selected file to be viewed.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.4]
* @param int $licenseId
* @param int $fileId
* @return \Symfony\Component\HttpFoundation\Response
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($licenseId = null, $fileId = null, $download = true)
{
$license = License::find($licenseId);
// the license is valid
if (isset($license->id)) {
$this->authorize('view', $license);
$this->authorize('licenses.files', $license);
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $license->id)->find($fileId)) {
$file = 'private_uploads/licenses/'.$log->filename;
try {
return StorageHelper::showOrDownloadFile($file, $log->filename);
} catch (\Exception $e) {
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.file_not_found'));
}
}
// The log record doesn't exist somehow
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.log_record_not_found'));
}
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
}
}

View File

@ -1,111 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Helpers\StorageHelper;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\Location;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Storage;
use \Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class LocationsFilesController extends Controller
{
/**
* Upload a file to the server.
*
* @param UploadFileRequest $request
* @param int $modelId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*@since [v1.0]
* @author [A. Gianotto] [<snipe@snipe.net>]
*/
public function store(UploadFileRequest $request, Location $location) : RedirectResponse
{
$this->authorize('update', $location);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/locations')) {
Storage::makeDirectory('private_uploads/locations', 775);
}
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/locations/','location-'.$location->id, $file);
$location->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->withFragment('files')->with('success', trans('general.file_upload_success'));
}
return redirect()->back()->withFragment('files')->with('error', trans('admin/hardware/message.upload.nofiles'));
}
/**
* Check for permissions and display the file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $modelId
* @param int $fileId
* @since [v1.0]
*/
public function show(Location $location, $fileId = null) : StreamedResponse | Response | RedirectResponse | BinaryFileResponse
{
$this->authorize('view', $location);
if (! $log = Actionlog::find($fileId)) {
return redirect()->back()->withFragment('files')->with('error', 'No matching file record');
}
$file = 'private_uploads/locations/'.$log->filename;
if (! Storage::exists($file)) {
return redirect()->back()->withFragment('files')->with('error', 'No matching file on server');
}
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
}
return StorageHelper::downloader($file);
}
/**
* Delete the associated file
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $modelId
* @param int $fileId
* @since [v1.0]
*/
public function destroy(Location $location, $fileId = null) : RedirectResponse
{
$rel_path = 'private_uploads/locations';
$this->authorize('update', $location);
$log = Actionlog::find($fileId);
if ($log) {
// This should be moved to purge
// if (Storage::exists($rel_path.'/'.$log->filename)) {
// Storage::delete($rel_path.'/'.$log->filename);
// }
$log->delete();
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
}
}

View File

@ -4,7 +4,7 @@ namespace App\Http\Controllers;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Maintenance;
use App\Models\Company;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
@ -18,29 +18,23 @@ use \Illuminate\Http\RedirectResponse;
*
* @version v2.0
*/
class AssetMaintenancesController extends Controller
class MaintenancesController extends Controller
{
/**
* Returns a view that invokes the ajax tables which actually contains
* the content for the asset maintenances listing, which is generated in getDatatable.
*
* @todo This should be replaced with middleware and/or policies
* @see AssetMaintenancesController::getDatatable() method that generates the JSON response
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
* the content for the asset maintenances listing.
*/
public function index() : View
{
$this->authorize('view', Asset::class);
return view('asset_maintenances/index');
return view('maintenances.index');
}
/**
* Returns a form view to create a new asset maintenance.
*
* @see AssetMaintenancesController::postCreate() method that stores the data
* @see MaintenancesController::postCreate() method that stores the data
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
@ -56,16 +50,16 @@ class AssetMaintenancesController extends Controller
$asset->asset_id = $asset->id;
}
return view('asset_maintenances/edit')
->with('assetMaintenanceType', AssetMaintenance::getImprovementOptions())
return view('maintenances/edit')
->with('maintenanceType', Maintenance::getImprovementOptions())
->with('asset', $asset)
->with('item', new AssetMaintenance);
->with('item', new Maintenance);
}
/**
* Validates and stores the new asset maintenance
*
* @see AssetMaintenancesController::getCreate() method for the form
* @see MaintenancesController::getCreate() method for the form
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
@ -79,73 +73,73 @@ class AssetMaintenancesController extends Controller
// Loop through the selected assets
foreach ($assets as $asset) {
$assetMaintenance = new AssetMaintenance();
$assetMaintenance->supplier_id = $request->input('supplier_id');
$assetMaintenance->is_warranty = $request->input('is_warranty');
$assetMaintenance->cost = $request->input('cost');
$assetMaintenance->notes = $request->input('notes');
$maintenance = new Maintenance();
$maintenance->supplier_id = $request->input('supplier_id');
$maintenance->is_warranty = $request->input('is_warranty');
$maintenance->cost = $request->input('cost');
$maintenance->notes = $request->input('notes');
// Save the asset maintenance data
$assetMaintenance->asset_id = $asset->id;
$assetMaintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
$assetMaintenance->title = $request->input('title');
$assetMaintenance->start_date = $request->input('start_date');
$assetMaintenance->completion_date = $request->input('completion_date');
$assetMaintenance->created_by = auth()->id();
$maintenance->asset_id = $asset->id;
$maintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
$maintenance->name = $request->input('name');
$maintenance->start_date = $request->input('start_date');
$maintenance->completion_date = $request->input('completion_date');
$maintenance->created_by = auth()->id();
if (($assetMaintenance->completion_date !== null)
&& ($assetMaintenance->start_date !== '')
&& ($assetMaintenance->start_date !== '0000-00-00')
if (($maintenance->completion_date !== null)
&& ($maintenance->start_date !== '')
&& ($maintenance->start_date !== '0000-00-00')
) {
$startDate = Carbon::parse($assetMaintenance->start_date);
$completionDate = Carbon::parse($assetMaintenance->completion_date);
$assetMaintenance->asset_maintenance_time = (int) $completionDate->diffInDays($startDate, true);
$startDate = Carbon::parse($maintenance->start_date);
$completionDate = Carbon::parse($maintenance->completion_date);
$maintenance->asset_maintenance_time = (int) $completionDate->diffInDays($startDate, true);
}
$assetMaintenance = $request->handleImages($assetMaintenance);
$maintenance = $request->handleImages($maintenance);
// Was the asset maintenance created?
if (!$assetMaintenance->save()) {
return redirect()->back()->withInput()->withErrors($assetMaintenance->getErrors());
if (!$maintenance->save()) {
return redirect()->back()->withInput()->withErrors($maintenance->getErrors());
}
}
return redirect()->route('maintenances.index')
->with('success', trans('admin/asset_maintenances/message.create.success'));
->with('success', trans('admin/maintenances/message.create.success'));
}
/**
* Returns a form view to edit a selected asset maintenance.
*
* @see AssetMaintenancesController::postEdit() method that stores the data
* @see MaintenancesController::postEdit() method that stores the data
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
*/
public function edit(AssetMaintenance $maintenance) : View | RedirectResponse
public function edit(Maintenance $maintenance) : View | RedirectResponse
{
$this->authorize('update', Asset::class);
$this->authorize('update', $maintenance->asset);
return view('asset_maintenances/edit')
return view('maintenances/edit')
->with('selected_assets', $maintenance->asset->pluck('id')->toArray())
->with('asset_ids', request()->input('asset_ids', []))
->with('assetMaintenanceType', AssetMaintenance::getImprovementOptions())
->with('maintenanceType', Maintenance::getImprovementOptions())
->with('item', $maintenance);
}
/**
* Validates and stores an update to an asset maintenance
*
* @see AssetMaintenancesController::postEdit() method that stores the data
* @see MaintenancesController::postEdit() method that stores the data
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @param Request $request
* @param int $assetMaintenanceId
* @param int $maintenanceId
* @version v1.0
* @since [v1.8]
*/
public function update(ImageUploadRequest $request, AssetMaintenance $maintenance) : View | RedirectResponse
public function update(ImageUploadRequest $request, Maintenance $maintenance) : View | RedirectResponse
{
$this->authorize('update', Asset::class);
$this->authorize('update', $maintenance->asset);
@ -155,7 +149,7 @@ class AssetMaintenancesController extends Controller
$maintenance->cost = $request->input('cost');
$maintenance->notes = $request->input('notes');
$maintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
$maintenance->title = $request->input('title');
$maintenance->name = $request->input('name');
$maintenance->start_date = $request->input('start_date');
$maintenance->completion_date = $request->input('completion_date');
@ -182,7 +176,7 @@ class AssetMaintenancesController extends Controller
if ($maintenance->save()) {
return redirect()->route('maintenances.index')
->with('success', trans('admin/asset_maintenances/message.edit.success'));
->with('success', trans('admin/maintenances/message.edit.success'));
}
return redirect()->back()->withInput()->withErrors($maintenance->getErrors());
@ -192,11 +186,11 @@ class AssetMaintenancesController extends Controller
* Delete an asset maintenance
*
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @param int $assetMaintenanceId
* @param int $maintenanceId
* @version v1.0
* @since [v1.8]
*/
public function destroy(AssetMaintenance $maintenance) : RedirectResponse
public function destroy(Maintenance $maintenance) : RedirectResponse
{
$this->authorize('update', Asset::class);
$this->authorize('update', $maintenance->asset);
@ -204,19 +198,19 @@ class AssetMaintenancesController extends Controller
$maintenance->delete();
// Redirect to the asset_maintenance management page
return redirect()->route('maintenances.index')
->with('success', trans('admin/asset_maintenances/message.delete.success'));
->with('success', trans('admin/maintenances/message.delete.success'));
}
/**
* View an asset maintenance
*
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @param int $assetMaintenanceId
* @param int $maintenanceId
* @version v1.0
* @since [v1.8]
*/
public function show(AssetMaintenance $maintenance) : View | RedirectResponse
public function show(Maintenance $maintenance) : View | RedirectResponse
{
return view('asset_maintenances/view')->with('assetMaintenance', $maintenance);
return view('maintenances.view')->with('maintenance', $maintenance);
}
}

View File

@ -9,7 +9,7 @@ use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Category;
use App\Models\AssetMaintenance;
use App\Models\Maintenance;
use App\Models\CheckoutAcceptance;
use App\Models\Company;
use App\Models\CustomField;
@ -17,13 +17,11 @@ use App\Models\Depreciation;
use App\Models\License;
use App\Models\ReportTemplate;
use App\Models\Setting;
use App\Notifications\CheckoutAssetNotification;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Notification;
use \Illuminate\Contracts\View\View;
use League\Csv\Reader;
use Symfony\Component\HttpFoundation\StreamedResponse;
@ -1038,11 +1036,11 @@ class ReportsController extends Controller
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
public function getAssetMaintenancesReport() : View
public function getMaintenancesReport() : View
{
$this->authorize('reports.view');
return view('reports.asset_maintenances');
return view('reports.maintenances');
}
/**
@ -1051,11 +1049,11 @@ class ReportsController extends Controller
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
public function exportAssetMaintenancesReport() : Response
public function exportMaintenancesReport() : Response
{
$this->authorize('reports.view');
// Grab all the improvements
$assetMaintenances = AssetMaintenance::with('asset', 'supplier')
$Maintenances = Maintenance::with('asset', 'supplier')
->orderBy('created_at', 'DESC')
->get();
@ -1063,36 +1061,36 @@ class ReportsController extends Controller
$header = [
trans('admin/hardware/table.asset_tag'),
trans('admin/asset_maintenances/table.asset_name'),
trans('admin/maintenances/table.asset_name'),
trans('general.supplier'),
trans('admin/asset_maintenances/form.asset_maintenance_type'),
trans('admin/asset_maintenances/form.title'),
trans('admin/asset_maintenances/form.start_date'),
trans('admin/asset_maintenances/form.completion_date'),
trans('admin/asset_maintenances/form.asset_maintenance_time'),
trans('admin/asset_maintenances/form.cost'),
trans('admin/maintenances/form.asset_maintenance_type'),
trans('admin/maintenances/form.title'),
trans('admin/maintenances/form.start_date'),
trans('admin/maintenances/form.completion_date'),
trans('admin/maintenances/form.asset_maintenance_time'),
trans('admin/maintenances/form.cost'),
];
$header = array_map('trim', $header);
$rows[] = implode(',', $header);
foreach ($assetMaintenances as $assetMaintenance) {
foreach ($Maintenances as $maintenance) {
$row = [];
$row[] = str_replace(',', '', e($assetMaintenance->asset->asset_tag));
$row[] = str_replace(',', '', e($assetMaintenance->asset->name));
$row[] = str_replace(',', '', e($assetMaintenance->supplier->name));
$row[] = e($assetMaintenance->improvement_type);
$row[] = e($assetMaintenance->title);
$row[] = e($assetMaintenance->start_date);
$row[] = e($assetMaintenance->completion_date);
if (is_null($assetMaintenance->asset_maintenance_time)) {
$row[] = str_replace(',', '', e($maintenance->asset->asset_tag));
$row[] = str_replace(',', '', e($maintenance->asset->name));
$row[] = str_replace(',', '', e($maintenance->supplier->name));
$row[] = e($maintenance->improvement_type);
$row[] = e($maintenance->name);
$row[] = e($maintenance->start_date);
$row[] = e($maintenance->completion_date);
if (is_null($maintenance->asset_maintenance_time)) {
$improvementTime = (int) Carbon::now()
->diffInDays(Carbon::parse($assetMaintenance->start_date), true);
->diffInDays(Carbon::parse($maintenance->start_date), true);
} else {
$improvementTime = (int) $assetMaintenance->asset_maintenance_time;
$improvementTime = (int) $maintenance->asset_maintenance_time;
}
$row[] = $improvementTime;
$row[] = trans('general.currency') . Helper::formatCurrencyOutput($assetMaintenance->cost);
$row[] = trans('general.currency') . Helper::formatCurrencyOutput($maintenance->cost);
$rows[] = implode(',', $row);
}

View File

@ -4,7 +4,6 @@ namespace App\Http\Controllers;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Supplier;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\RedirectResponse;
use \Illuminate\Contracts\View\View;
@ -122,7 +121,7 @@ class SuppliersController extends Controller
public function destroy($supplierId) : RedirectResponse
{
$this->authorize('delete', Supplier::class);
if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->find($supplierId))) {
if (is_null($supplier = Supplier::with('maintenances', 'assets', 'licenses')->withCount('maintenances as maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->find($supplierId))) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.not_found'));
}
@ -130,8 +129,8 @@ class SuppliersController extends Controller
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_assets', ['asset_count' => (int) $supplier->assets_count]));
}
if ($supplier->asset_maintenances_count > 0) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_maintenances', ['asset_maintenances_count' => $supplier->asset_maintenances_count]));
if ($supplier->maintenances_count > 0) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_maintenances', ['maintenances_count' => $supplier->maintenances_count]));
}
if ($supplier->licenses_count > 0) {

View File

@ -0,0 +1,209 @@
<?php
namespace App\Http\Controllers;
use App\Helpers\StorageHelper;
use App\Http\Requests\UploadFileRequest;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Maintenance;
use App\Models\AssetModel;
use App\Models\Component;
use App\Models\Consumable;
use App\Models\License;
use App\Models\Location;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
/**
* This controller provide the health route for
* the Snipe-IT Asset Management application.
*
* @version v1.0
*
* @return \Illuminate\Http\JsonResponse
*/
class UploadedFilesController extends Controller
{
static $map_object_type = [
'accessories' => Accessory::class,
'maintenances' => Maintenance::class,
'assets' => Asset::class,
'components' => Component::class,
'consumables' => Consumable::class,
'hardware' => Asset::class,
'licenses' => License::class,
'locations' => Location::class,
'models' => AssetModel::class,
'users' => User::class,
];
static $map_storage_path = [
'accessories' => 'private_uploads/accessories/',
'maintenances' => 'private_uploads/maintenances/',
'assets' => 'private_uploads/assets/',
'components' => 'private_uploads/components/',
'consumables' => 'private_uploads/consumables/',
'hardware' => 'private_uploads/assets/',
'licenses' => 'private_uploads/licenses/',
'locations' => 'private_uploads/locations/',
'models' => 'private_uploads/models/',
'users' => 'private_uploads/users/',
];
static $map_file_prefix= [
'accessories' => 'accessory',
'maintenances' => 'maintenance',
'assets' => 'asset',
'components' => 'component',
'consumables' => 'consumable',
'hardware' => 'asset',
'licenses' => 'license',
'locations' => 'location',
'models' => 'model',
'users' => 'user',
];
/**
* Accepts a POST to upload a file to the server.
*
* @param \App\Http\Requests\UploadFileRequest $request
* @param string $object_type the type of object to upload the file to
* @param int $id the ID of the object to store so we can check permisisons
* @since [v8.2.2]
* @author [A. Gianotto <snipe@snipe.net>]
*/
public function store(UploadFileRequest $request, $object_type, $id) : RedirectResponse
{
// Check the permissions to make sure the user can view the object
$object = self::$map_object_type[$object_type]::find($id);
$this->authorize('update', $object);
if (!$object) {
return redirect()->back()->withFragment('files')->with('error',trans('general.file_upload_status.invalid_object'));
}
// If the file storage directory doesn't exist, create it
if (! Storage::exists(self::$map_storage_path[$object_type])) {
Storage::makeDirectory(self::$map_storage_path[$object_type], 775);
}
if ($request->hasFile('file')) {
// Loop over the attached files and add them to the object
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile(self::$map_storage_path[$object_type], self::$map_file_prefix[$object_type].'-'.$object->id, $file);
$files[] = $file_name;
$object->logUpload($file_name, $request->get('notes'));
}
$files = Actionlog::select('action_logs.*')->where('action_type', '=', 'uploaded')
->where('item_type', '=', self::$map_object_type[$object_type])
->where('item_id', '=', $id)->whereIn('filename', $files)
->get();
return redirect()->back()->withFragment('files')->with('success', trans_choice('general.file_upload_status.upload.success', count($files)));
}
// No files were submitted
return redirect()->back()->withFragment('files')->with('error', trans('general.file_upload_status.nofiles'));
}
/**
* Check for permissions and display the file.
* This isn't currently used, but is here for future use.
*
* @param \App\Http\Requests\UploadFileRequest $request
* @param string $object_type the type of object to upload the file to
* @param int $id the ID of the object to delete from so we can check permisisons
* @param $file_id the ID of the file to show from the action_logs table
* @since [v8.2.2]
* @author [A. Gianotto <snipe@snipe.net>]
*/
public function show($object_type, $id, $file_id) : RedirectResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse
{
// Check the permissions to make sure the user can view the object
$object = self::$map_object_type[$object_type]::find($id);
$this->authorize('view', $object);
if (!$object) {
return redirect()->back()->withFragment('files')->with('error',trans('general.file_upload_status.invalid_object'));
}
// Check that the file being requested exists for the object
if (! $log = Actionlog::whereNotNull('filename')->where('item_type', self::$map_object_type[$object_type])->where('item_id', $object->id)->find($file_id))
{
return redirect()->back()->withFragment('files')->with('error', trans('general.file_upload_status.invalid_id'));
}
if (! Storage::exists(self::$map_storage_path[$object_type].'/'.$log->filename))
{
return redirect()->back()->withFragment('files')->with('error', trans('general.file_upload_status.file_not_found'));
}
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download(self::$map_storage_path[$object_type].'/'.$log->filename, $log->filename, $headers);
}
return StorageHelper::downloader(self::$map_storage_path[$object_type].'/'.$log->filename);
}
/**
* Delete the associated file
*
* @param \App\Http\Requests\UploadFileRequest $request
* @param string $object_type the type of object to upload the file to
* @param int $id the ID of the object to delete from so we can check permisisons
* @param $file_id the ID of the file to delete from the action_logs table
* @since [v8.2.2]
* @author [A. Gianotto <snipe@snipe.net>]
*/
public function destroy($object_type, $id, $file_id) : RedirectResponse
{
// Check the permissions to make sure the user can view the object
$object = self::$map_object_type[$object_type]::find($id);
$this->authorize('update', self::$map_object_type[$object_type]);
if (!$object) {
return redirect()->back()->withFragment('files')->with('error',trans('general.file_upload_status.invalid_object'));
}
// Check for the file
$log = Actionlog::find($file_id)->where('item_type', self::$map_object_type[$object_type])
->where('item_id', $object->id)->first();
if ($log) {
// Check the file actually exists, and delete it
if (Storage::exists(self::$map_storage_path[$object_type].'/'.$log->filename)) {
Storage::delete(self::$map_storage_path[$object_type].'/'.$log->filename);
}
// Delete the record of the file
if ($log->delete()) {
return redirect()->back()->withFragment('files')->with('success', trans_choice('general.file_upload_status.delete.success', 1));
}
}
// The file doesn't seem to really exist, so report an error
return redirect()->back()->withFragment('files')->with('success', trans_choice('general.file_upload_status.delete.error', 1));
}
}

View File

@ -1,119 +0,0 @@
<?php
namespace App\Http\Controllers\Users;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\User;
use Symfony\Component\HttpFoundation\JsonResponse;
use Illuminate\Support\Facades\Storage;
class UserFilesController extends Controller
{
/**
* Return JSON response with a list of user details for the getIndex() view.
*
* @param UploadFileRequest $request
* @param int $userId
* @return string JSON
* @throws \Illuminate\Auth\Access\AuthorizationException
*@author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.6]
*/
public function store(UploadFileRequest $request, User $user)
{
$this->authorize('update', $user);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/users')) {
Storage::makeDirectory('private_uploads/users', 775);
}
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/users/','user-'.$user->id, $file);
$user->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.upload.success'));
}
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
}
/**
* Delete file
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.6]
* @param int $userId
* @param int $fileId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($userId = null, $fileId = null)
{
if ($user = User::find($userId)) {
$this->authorize('delete', $user);
$rel_path = 'private_uploads/users';
if ($log = Actionlog::find($fileId)) {
$filename = $log->filename;
$log->delete();
if (Storage::exists($rel_path.'/'.$filename)) {
Storage::delete($rel_path.'/'.$filename);
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.deletefile.success'));
}
}
// The log record doesn't exist somehow
return redirect()->back()->with('success', trans('admin/users/message.deletefile.success'));
}
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', ['id' => $userId]));
}
/**
* Display/download the uploaded file
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.6]
* @param int $userId
* @param int $fileId
* @return mixed
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show(User $user, $fileId = null)
{
if (empty($fileId)) {
return redirect()->route('users.show')->with('error', 'Invalid file request');
}
$this->authorize('view', $user);
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $user->id)->find($fileId)) {
$file = 'private_uploads/users/'.$log->filename;
try {
return StorageHelper::showOrDownloadFile($file, $log->filename);
} catch (\Exception $e) {
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.file_not_found'));
}
}
// The log record doesn't exist somehow
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.log_record_not_found'));
}
}

View File

@ -71,25 +71,25 @@ class ImageUploadRequest extends Request
public function handleImages($item, $w = 600, $form_fieldname = 'image', $path = null, $db_fieldname = 'image')
{
$type = Str::snake(class_basename(get_class($item)));
$type = class_basename(get_class($item));
if (is_null($path)) {
\Log::debug('path is null');
$path = Str::of(str_plural($type))->snake();
$path = strtolower(str_plural($type));
if ($type == 'assetmodel') {
if ($type == 'AssetModel') {
$path = 'models';
}
if ($type == 'user') {
$path = 'avatars';
}
}
if (!Storage::exists($path)) {
Storage::makeDirectory($path);
if (!Storage::disk('public')->exists($path)) {
Storage::disk('public')->makeDirectory($path);
}
if ($this->offsetGet($form_fieldname) instanceof UploadedFile) {
@ -100,7 +100,6 @@ class ImageUploadRequest extends Request
if (isset($image)) {
if (!config('app.lock_passwords')) {
$ext = $image->guessExtension();
$file_name = $type.'-'.$form_fieldname.($item->id ?? '-'.$item->id).'-'.str_random(10).'.'.$ext;
@ -145,7 +144,7 @@ class ImageUploadRequest extends Request
// Remove Current image if exists
$item = $this->deleteExistingImage($item, $path, $db_fieldname);
$item->{$db_fieldname} = $file_name;
}
// If the user isn't uploading anything new but wants to delete their old image, do so

View File

@ -4,24 +4,24 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Maintenance;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
class AssetMaintenancesTransformer
class MaintenancesTransformer
{
public function transformAssetMaintenances(Collection $assetmaintenances, $total)
public function transformMaintenances(Collection $maintenances, $total)
{
$array = [];
foreach ($assetmaintenances as $assetmaintenance) {
$array[] = self::transformAssetMaintenance($assetmaintenance);
foreach ($maintenances as $assetmaintenance) {
$array[] = self::transformMaintenance($assetmaintenance);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformAssetMaintenance(AssetMaintenance $assetmaintenance)
public function transformMaintenance(Maintenance $assetmaintenance)
{
$array = [
'id' => (int) $assetmaintenance->id,
@ -34,7 +34,7 @@ class AssetMaintenancesTransformer
'created_at' => Helper::getFormattedDateObject($assetmaintenance->asset->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->asset->updated_at, 'datetime'),
] : null,
'image' => ($assetmaintenance->image != '') ? Storage::disk('public')->url('asset_maintenances/'.e($assetmaintenance->image)) : null,
'image' => ($assetmaintenance->image != '') ? Storage::disk('public')->url('maintenances/'.e($assetmaintenance->image)) : null,
'model' => (($assetmaintenance->asset) && ($assetmaintenance->asset->model)) ? [
'id' => (int) $assetmaintenance->asset->model->id,
'name'=> ($assetmaintenance->asset->model->name) ? e($assetmaintenance->asset->model->name).' '.e($assetmaintenance->asset->model->model_number) : null,
@ -50,7 +50,8 @@ class AssetMaintenancesTransformer
'name'=> ($assetmaintenance->asset->company->name) ? e($assetmaintenance->asset->company->name) : null,
] : null,
'title' => ($assetmaintenance->title) ? e($assetmaintenance->title) : null,
'name' => ($assetmaintenance->name) ? e($assetmaintenance->name) : null,
'title' => ($assetmaintenance->name) ? e($assetmaintenance->name) : null, // legacy to not change the shape of the API
'location' => (($assetmaintenance->asset) && ($assetmaintenance->asset->location)) ? [
'id' => (int) $assetmaintenance->asset->location->id,
'name'=> e($assetmaintenance->asset->location->name),

View File

@ -7,6 +7,7 @@ use App\Presenters\Presentable;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;
/**
* Model for the Actionlog (the table that keeps a historical log of
@ -458,30 +459,23 @@ class Actionlog extends SnipeModel
{
if (($this->action_type == 'accepted') || ($this->action_type == 'declined')) {
return route('log.storedeula.download', ['filename' => $this->filename]);
}
switch ($this->item_type) {
case Accessory::class:
return route('show.accessoryfile', [$this->item_id, $this->id]);
case Asset::class:
return route('show/assetfile', [$this->item_id, $this->id]);
case AssetModel::class:
return route('show/modelfile', [$this->item_id, $this->id]);
case Consumable::class:
return route('show.consumablefile', [$this->item_id, $this->id]);
case Component::class:
return route('show.componentfile', [$this->item_id, $this->id]);
case License::class:
return route('show.licensefile', [$this->item_id, $this->id]);
case Location::class:
return route('show/locationsfile', [$this->item_id, $this->id]);
case User::class:
return route('show/userfile', [$this->item_id, $this->id]);
default:
return null;
$object = Str::snake(str_plural(str_replace("App\Models\\", '', $this->item_type)));
if ($object == 'asset_models') {
$object = 'models';
}
return route('ui.files.show', [
'object_type' => $object,
'id' => $this->item_id,
'file_id' => $this->id,
]);
}
public function uploads_file_path()
@ -497,7 +491,7 @@ class Actionlog extends SnipeModel
case Asset::class:
return 'private_uploads/assets/'.$this->filename;
case AssetModel::class:
return 'private_uploads/assetmodels/'.$this->filename;
return 'private_uploads/models/'.$this->filename;
case Consumable::class:
return 'private_uploads/consumables/'.$this->filename;
case Component::class:
@ -506,6 +500,8 @@ class Actionlog extends SnipeModel
return 'private_uploads/licenses/'.$this->filename;
case Location::class:
return 'private_uploads/locations/'.$this->filename;
case Maintenance::class:
return 'private_uploads/maintenances/'.$this->filename;
case User::class:
return 'private_uploads/users/'.$this->filename;
default:
@ -514,11 +510,6 @@ class Actionlog extends SnipeModel
}
// Manually sets $this->source for determineActionSource()
public function setActionSource($source = null): void
{

View File

@ -771,9 +771,9 @@ class Asset extends Depreciable
* @since 1.0
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetmaintenances()
public function maintenances()
{
return $this->hasMany(\App\Models\AssetMaintenance::class, 'asset_id')
return $this->hasMany(\App\Models\Maintenance::class, 'asset_id')
->orderBy('created_at', 'desc');
}

View File

@ -4,31 +4,34 @@ namespace App\Models;
use App\Helpers\Helper;
use App\Models\Traits\Searchable;
use App\Presenters\Presentable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
use App\Models\Traits\HasUploads;
/**
* Model for Asset Maintenances.
*
* @version v1.0
*/
class AssetMaintenance extends Model implements ICompanyableChild
class Maintenance extends SnipeModel implements ICompanyableChild
{
use HasFactory;
use HasUploads;
use SoftDeletes;
use CompanyableChildTrait;
use ValidatingTrait;
use Loggable, Presentable;
protected $table = 'asset_maintenances';
protected $table = 'maintenances';
protected $rules = [
'asset_id' => 'required|integer',
'supplier_id' => 'nullable|integer',
'asset_maintenance_type' => 'required',
'title' => 'required|max:100',
'name' => 'required|max:100',
'is_warranty' => 'boolean',
'start_date' => 'required|date_format:Y-m-d',
'completion_date' => 'date_format:Y-m-d|nullable|after_or_equal:start_date',
@ -43,7 +46,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
* @var array
*/
protected $fillable = [
'title',
'name',
'asset_id',
'supplier_id',
'asset_maintenance_type',
@ -64,7 +67,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
*/
protected $searchableAttributes =
[
'title',
'name',
'notes',
'asset_maintenance_type',
'cost',
@ -100,14 +103,14 @@ class AssetMaintenance extends Model implements ICompanyableChild
public static function getImprovementOptions()
{
return [
trans('admin/asset_maintenances/general.maintenance') => trans('admin/asset_maintenances/general.maintenance'),
trans('admin/asset_maintenances/general.repair') => trans('admin/asset_maintenances/general.repair'),
trans('admin/asset_maintenances/general.upgrade') => trans('admin/asset_maintenances/general.upgrade'),
trans('admin/asset_maintenances/general.pat_test') => trans('admin/asset_maintenances/general.pat_test'),
trans('admin/asset_maintenances/general.calibration') => trans('admin/asset_maintenances/general.calibration'),
trans('admin/asset_maintenances/general.software_support') => trans('admin/asset_maintenances/general.software_support'),
trans('admin/asset_maintenances/general.hardware_support') => trans('admin/asset_maintenances/general.hardware_support'),
trans('admin/asset_maintenances/general.configuration_change') => trans('admin/asset_maintenances/general.configuration_change'),
trans('admin/maintenances/general.maintenance') => trans('admin/maintenances/general.maintenance'),
trans('admin/maintenances/general.repair') => trans('admin/maintenances/general.repair'),
trans('admin/maintenances/general.upgrade') => trans('admin/maintenances/general.upgrade'),
trans('admin/maintenances/general.pat_test') => trans('admin/maintenances/general.pat_test'),
trans('admin/maintenances/general.calibration') => trans('admin/maintenances/general.calibration'),
trans('admin/maintenances/general.software_support') => trans('admin/maintenances/general.software_support'),
trans('admin/maintenances/general.hardware_support') => trans('admin/maintenances/general.hardware_support'),
trans('admin/maintenances/general.configuration_change') => trans('admin/maintenances/general.configuration_change'),
];
}
@ -166,6 +169,21 @@ class AssetMaintenance extends Model implements ICompanyableChild
return $this->belongsTo(\App\Models\Asset::class, 'asset_id')
->withTrashed();
}
/**
* Get the maintenance logs
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v8.2.2]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetlog()
{
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
->where('item_type', '=', self::class)
->orderBy('created_at', 'desc')
->withTrashed();
}
/**
@ -187,6 +205,11 @@ class AssetMaintenance extends Model implements ICompanyableChild
->withTrashed();
}
public function getDisplayNameAttribute()
{
return $this->name;
}
/**
* -----------------------------------------------
* BEGIN QUERY SCOPES
@ -203,7 +226,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
*/
public function scopeOrderBySupplier($query, $order)
{
return $query->leftJoin('suppliers as suppliers_maintenances', 'asset_maintenances.supplier_id', '=', 'suppliers_maintenances.id')
return $query->leftJoin('suppliers as suppliers_maintenances', 'maintenances.supplier_id', '=', 'suppliers_maintenances.id')
->orderBy('suppliers_maintenances.name', $order);
}
@ -219,7 +242,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
*/
public function scopeOrderByTag($query, $order)
{
return $query->leftJoin('assets', 'asset_maintenances.asset_id', '=', 'assets.id')
return $query->leftJoin('assets', 'maintenances.asset_id', '=', 'assets.id')
->orderBy('assets.asset_tag', $order);
}
@ -233,7 +256,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
*/
public function scopeOrderByAssetName($query, $order)
{
return $query->leftJoin('assets', 'asset_maintenances.asset_id', '=', 'assets.id')
return $query->leftJoin('assets', 'maintenances.asset_id', '=', 'assets.id')
->orderBy('assets.name', $order);
}
@ -247,7 +270,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
*/
public function scopeOrderByAssetSerial($query, $order)
{
return $query->leftJoin('assets', 'asset_maintenances.asset_id', '=', 'assets.id')
return $query->leftJoin('assets', 'maintenances.asset_id', '=', 'assets.id')
->orderBy('assets.serial', $order);
}
@ -261,7 +284,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
*/
public function scopeOrderStatusName($query, $order)
{
return $query->join('assets as maintained_asset', 'asset_maintenances.asset_id', '=', 'maintained_asset.id')
return $query->join('assets as maintained_asset', 'maintenances.asset_id', '=', 'maintained_asset.id')
->leftjoin('status_labels as maintained_asset_status', 'maintained_asset_status.id', '=', 'maintained_asset.status_id')
->orderBy('maintained_asset_status.name', $order);
}
@ -276,7 +299,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
*/
public function scopeOrderLocationName($query, $order)
{
return $query->join('assets as maintained_asset', 'asset_maintenances.asset_id', '=', 'maintained_asset.id')
return $query->join('assets as maintained_asset', 'maintenances.asset_id', '=', 'maintained_asset.id')
->leftjoin('locations as maintained_asset_location', 'maintained_asset_location.id', '=', 'maintained_asset.location_id')
->orderBy('maintained_asset_location.name', $order);
}
@ -286,6 +309,6 @@ class AssetMaintenance extends Model implements ICompanyableChild
*/
public function scopeOrderByCreatedBy($query, $order)
{
return $query->leftJoin('users as admin_sort', 'asset_maintenances.created_by', '=', 'admin_sort.id')->select('asset_maintenances.*')->orderBy('admin_sort.first_name', $order)->orderBy('admin_sort.last_name', $order);
return $query->leftJoin('users as admin_sort', 'maintenances.created_by', '=', 'admin_sort.id')->select('maintenances.*')->orderBy('admin_sort.first_name', $order)->orderBy('admin_sort.last_name', $order);
}
}

View File

@ -7,7 +7,7 @@ use App\Models\Traits\Searchable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
use \Illuminate\Database\Eloquent\Relations\Relation;
class Supplier extends SnipeModel
{
use HasFactory;
@ -133,7 +133,7 @@ class Supplier extends SnipeModel
* Establishes the supplier -> admin user relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @return \Illuminate\Database\Eloquent\Relations\Relation
* @return Relation
*/
public function adminuser()
{
@ -147,9 +147,9 @@ class Supplier extends SnipeModel
* @since [v1.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function asset_maintenances()
public function maintenances(): Relation
{
return $this->hasMany(\App\Models\AssetMaintenance::class, 'supplier_id');
return $this->hasMany(\App\Models\Maintenance::class, 'supplier_id');
}
/**

View File

@ -409,9 +409,9 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assetmaintenances()
public function maintenances()
{
return $this->hasMany(\App\Models\AssetMaintenance::class, 'user_id')->withTrashed();
return $this->hasMany(\App\Models\Maintenance::class, 'user_id')->withTrashed();
}
/**

View File

@ -20,7 +20,11 @@ class ComponentObserver
$logAction->item_type = Component::class;
$logAction->item_id = $component->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->action_date = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
if($component->imported) {
$logAction->setActionSource('importer');
}
$logAction->logaction('update');
}
@ -37,6 +41,7 @@ class ComponentObserver
$logAction->item_type = Component::class;
$logAction->item_id = $component->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->action_date = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
if($component->imported) {
$logAction->setActionSource('importer');
@ -56,6 +61,7 @@ class ComponentObserver
$logAction->item_type = Component::class;
$logAction->item_id = $component->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->action_date = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
$logAction->logaction('delete');
}

View File

@ -0,0 +1,74 @@
<?php
namespace App\Observers;
use App\Models\Actionlog;
use App\Models\Maintenance;
use App\Models\Asset;
class MaintenanceObserver
{
/**
* Listen to the User created event.
*
* @param Maintenance $maintenance
* @return void
*/
public function updated(Maintenance $maintenance)
{
$logAction = new Actionlog();
$logAction->item_type = Maintenance::class;
$logAction->item_id = $maintenance->id;
$logAction->target_type = Asset::class;
$logAction->target_id = $maintenance->asset_id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->action_date = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
if($maintenance->imported) {
$logAction->setActionSource('importer');
}
$logAction->logaction('update');
}
/**
* Listen to the Component created event when
* a new component is created.
*
* @param Maintenance $maintenance
* @return void
*/
public function created(Maintenance $maintenance)
{
$logAction = new Actionlog();
$logAction->item_type = Maintenance::class;
$logAction->item_id = $maintenance->id;
$logAction->target_type = Asset::class;
$logAction->target_id = $maintenance->asset_id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->action_date = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
if($maintenance->imported) {
$logAction->setActionSource('importer');
}
$logAction->logaction('create');
}
/**
* Listen to the Component deleting event.
*
* @param Maintenance $maintenance
* @return void
*/
public function deleting(Maintenance $maintenance)
{
$logAction = new Actionlog();
$logAction->item_type = Maintenance::class;
$logAction->item_id = $maintenance->id;
$logAction->target_type = Asset::class;
$logAction->target_id = $maintenance->asset_id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->action_date = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
$logAction->logaction('delete');
}
}

View File

@ -5,7 +5,7 @@ namespace App\Presenters;
/**
* Class AssetModelPresenter
*/
class AssetMaintenancesPresenter extends Presenter
class MaintenancesPresenter extends Presenter
{
/**
* Json Column Layout for bootstrap table
@ -22,7 +22,7 @@ class AssetMaintenancesPresenter extends Presenter
'title' => trans('general.id'),
'visible' => false,
], [
'field' => 'title',
'field' => 'name',
'searchable' => true,
'sortable' => true,
'switchable' => true,
@ -51,7 +51,7 @@ class AssetMaintenancesPresenter extends Presenter
'field' => 'asset_name',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/asset_maintenances/table.asset_name'),
'title' => trans('admin/maintenances/table.asset_name'),
'formatter' => 'assetNameLinkFormatter',
], [
'field' => 'asset_tag',
@ -98,35 +98,35 @@ class AssetMaintenancesPresenter extends Presenter
'field' => 'asset_maintenance_type',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/asset_maintenances/form.asset_maintenance_type'),
'title' => trans('admin/maintenances/form.asset_maintenance_type'),
], [
'field' => 'start_date',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/asset_maintenances/form.start_date'),
'title' => trans('admin/maintenances/form.start_date'),
'formatter' => 'dateDisplayFormatter',
], [
'field' => 'completion_date',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/asset_maintenances/form.completion_date'),
'title' => trans('admin/maintenances/form.completion_date'),
'formatter' => 'dateDisplayFormatter',
], [
'field' => 'notes',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/asset_maintenances/form.notes'),
'title' => trans('admin/maintenances/form.notes'),
], [
'field' => 'is_warranty',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/asset_maintenances/table.is_warranty'),
'title' => trans('admin/maintenances/table.is_warranty'),
'formatter' => 'trueFalseFormatter'
], [
'field' => 'cost',
'searchable' => true,
'sortable' => true,
'title' => trans('admin/asset_maintenances/form.cost'),
'title' => trans('admin/maintenances/form.cost'),
'class' => 'text-right',
], [
'field' => 'created_by',

View File

@ -7,6 +7,7 @@ use App\Models\Asset;
use App\Models\Component;
use App\Models\Consumable;
use App\Models\License;
use App\Models\Maintenance;
use App\Models\User;
use App\Models\Setting;
use App\Models\SnipeSCIMConfig;
@ -17,6 +18,7 @@ use App\Observers\ComponentObserver;
use App\Observers\ConsumableObserver;
use App\Observers\LicenseObserver;
use App\Observers\SettingObserver;
use App\Observers\MaintenanceObserver;
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
@ -67,6 +69,7 @@ class AppServiceProvider extends ServiceProvider
Schema::defaultStringLength(191);
Asset::observe(AssetObserver::class);
Maintenance::observe(MaintenanceObserver::class);
User::observe(UserObserver::class);
Accessory::observe(AccessoryObserver::class);
Component::observe(ComponentObserver::class);

View File

@ -2,7 +2,7 @@
use App\Models\Accessory;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Maintenance;
use App\Models\AssetModel;
use App\Models\Category;
use App\Models\Company;
@ -413,14 +413,14 @@ class BreadcrumbsServiceProvider extends ServiceProvider
->push(trans('general.create'), route('maintenances.create'))
);
Breadcrumbs::for('maintenances.show', fn (Trail $trail, AssetMaintenance $maintenance) =>
Breadcrumbs::for('maintenances.show', fn (Trail $trail, Maintenance $maintenance) =>
$trail->parent('maintenances.index', route('maintenances.index'))
->push($maintenance->title, route('maintenances.show', $maintenance))
->push($maintenance->name, route('maintenances.show', $maintenance))
);
Breadcrumbs::for('maintenances.edit', fn (Trail $trail, AssetMaintenance $maintenance) =>
Breadcrumbs::for('maintenances.edit', fn (Trail $trail, Maintenance $maintenance) =>
$trail->parent('maintenances.index', route('maintenances.index'))
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $maintenance->title]), route('maintenances.edit', $maintenance))
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $maintenance->name]), route('maintenances.edit', $maintenance))
);

View File

@ -65,8 +65,8 @@ class SettingsServiceProvider extends ServiceProvider
return 'assets/';
});
app()->singleton('asset_maintenances_path', function () {
return 'asset_maintenances/';
app()->singleton('maintenances_path', function () {
return 'maintenances/';
});
app()->singleton('audits_upload_path', function () {

View File

@ -3,18 +3,18 @@
namespace Database\Factories;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Maintenance;
use App\Models\Supplier;
use Illuminate\Database\Eloquent\Factories\Factory;
class AssetMaintenanceFactory extends Factory
class MaintenanceFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = AssetMaintenance::class;
protected $model = Maintenance::class;
/**
* Define the model's default state.
@ -27,7 +27,7 @@ class AssetMaintenanceFactory extends Factory
'asset_id' => Asset::factory(),
'supplier_id' => Supplier::factory(),
'asset_maintenance_type' => $this->faker->randomElement(['maintenance', 'repair', 'upgrade']),
'title' => $this->faker->sentence(),
'name' => $this->faker->sentence(),
'start_date' => $this->faker->date(),
'is_warranty' => $this->faker->boolean(),
'notes' => $this->faker->paragraph(),

View File

@ -2,7 +2,7 @@
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Schema;
class CreateAssetMaintenancesTable extends Migration
{
@ -40,9 +40,9 @@
protected function getEnumFields()
{
return [
trans('admin/asset_maintenances/general.maintenance'),
trans('admin/asset_maintenances/general.repair'),
trans('admin/asset_maintenances/general.upgrade'),
trans('admin/maintenances/general.maintenance'),
trans('admin/maintenances/general.repair'),
trans('admin/maintenances/general.upgrade'),
];
}

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('asset_maintenances', function (Blueprint $table) {
$table->renameColumn('title', 'name');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('asset_maintenances', function (Blueprint $table) {
$table->renameColumn('name', 'title');
});
}
};

View File

@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::rename('asset_maintenances', 'maintenances');
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::rename('maintenances', 'asset_maintenances');
}
};

View File

@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use App\Models\Actionlog;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Actionlog::where('item_type', 'App\\Models\\AssetMaintenance')->update(['item_type' => 'App\\Models\\Maintenance']);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
}
};

View File

@ -53,7 +53,7 @@ class DatabaseSeeder extends Seeder
Model::reguard();
DB::table('imports')->truncate();
DB::table('asset_maintenances')->truncate();
DB::table('maintenances')->truncate();
DB::table('requested_assets')->truncate();
}
}

View File

@ -22,7 +22,7 @@ return array(
'success' => 'Verskaffer is suksesvol verwyder.',
'assoc_assets' => 'This supplier is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this supplier and try again. ',
'assoc_licenses' => 'This supplier is currently associated with :licenses_count licences(s) and cannot be deleted. Please update your licenses to no longer reference this supplier and try again. ',
'assoc_maintenances' => 'This supplier is currently associated with :asset_maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
'assoc_maintenances' => 'This supplier is currently associated with :maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
)
);

View File

@ -22,7 +22,7 @@ return array(
'success' => 'Supplier was deleted successfully.',
'assoc_assets' => 'This supplier is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this supplier and try again. ',
'assoc_licenses' => 'This supplier is currently associated with :licenses_count licences(s) and cannot be deleted. Please update your licenses to no longer reference this supplier and try again. ',
'assoc_maintenances' => 'This supplier is currently associated with :asset_maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
'assoc_maintenances' => 'This supplier is currently associated with :maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
)
);

View File

@ -22,7 +22,7 @@ return array(
'success' => 'تم حذف المورد بنجاح.',
'assoc_assets' => 'هذا المورد مرتبط حاليا مع :asset_count من الأصول على الاقل ولا يمكن حذفه. الرجاء تحديث الأصول لكي لا تشير الى هذا المورد ثم حاول مرة أخرى. ',
'assoc_licenses' => 'هذا المورد مرتبط حاليا مع :licenses_count من التراخيص ولا يمكن حذفه. الرجاء تحديث التراخيص الخاصة بك لكي لا تشير الى هذا المورد وحاول مرة أخرى. ',
'assoc_maintenances' => 'هذا المورد مرتبط حاليا مع :asset_maintenances_count من سندات صيانة الأصول ولا يمكن حذفه. الرجاء تحديث سندات صيانة الأصول الخاصة بك لكي لا تشير الى هذا المورد وحاول مرة أخرى. ',
'assoc_maintenances' => 'هذا المورد مرتبط حاليا مع :maintenances_count من سندات صيانة الأصول ولا يمكن حذفه. الرجاء تحديث سندات صيانة الأصول الخاصة بك لكي لا تشير الى هذا المورد وحاول مرة أخرى. ',
)
);

View File

@ -22,7 +22,7 @@ return array(
'success' => 'Доставчикът е изтрит.',
'assoc_assets' => 'Този доставчик е текущо асоцииран с :asset_count актива и не може да бъде изтрит. Моля, променете връзките на моделите по отношение на този доставчик и опитайте отново. ',
'assoc_licenses' => 'Този доставчик е текущо асоцииран с :licenses_count лиценза и не може да бъде изтрит. Моля, променете връзките на лицензите по отношение на този доставчик и опитайте отново. ',
'assoc_maintenances' => 'Този доставчик е текущо асоцииран с :asset_maintenances_count инвентаризации и не може да бъде изтрит. Моля, променете връзките на инвентаризациите по отношение на този доставчик и опитайте отново. ',
'assoc_maintenances' => 'Този доставчик е текущо асоцииран с :maintenances_count инвентаризации и не може да бъде изтрит. Моля, променете връзките на инвентаризациите по отношение на този доставчик и опитайте отново. ',
)
);

View File

@ -22,7 +22,7 @@ return array(
'success' => 'Supplier was deleted successfully.',
'assoc_assets' => 'This supplier is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this supplier and try again. ',
'assoc_licenses' => 'This supplier is currently associated with :licenses_count licences(s) and cannot be deleted. Please update your licenses to no longer reference this supplier and try again. ',
'assoc_maintenances' => 'This supplier is currently associated with :asset_maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
'assoc_maintenances' => 'This supplier is currently associated with :maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
)
);

View File

@ -22,7 +22,7 @@ return array(
'success' => 'Supplier was deleted successfully.',
'assoc_assets' => 'This supplier is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this supplier and try again. ',
'assoc_licenses' => 'This supplier is currently associated with :licenses_count licences(s) and cannot be deleted. Please update your licenses to no longer reference this supplier and try again. ',
'assoc_maintenances' => 'This supplier is currently associated with :asset_maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
'assoc_maintenances' => 'This supplier is currently associated with :maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
)
);

View File

@ -22,7 +22,7 @@ return array(
'success' => 'Dodavatel byl úspěšně smazán.',
'assoc_assets' => 'Tento dodavatel je v současné době přiřazen k :asset_count položkám majetku a nelze jej smazat. Aktualizujte svůj majetek tak, aby již tento dodavatel nebyl přiřazen a zkuste to znovu. ',
'assoc_licenses' => 'Tento dodavatel je v současné době spojen s :licenses_count licencemi a nelze jej smazat. Aktualizujte prosím své licence, abyste již tento dodavatel nebyl přiřazen a zkuste to znovu. ',
'assoc_maintenances' => 'Tento dodavatel je v současné době spojen s údržbou :asset_maintenances_count položek majetku a nemůže být smazán. Aktualizujte prosím údržbu vašeho majetku, aby již tento dodavatel nebyl přiřazen a zkuste to znovu. ',
'assoc_maintenances' => 'Tento dodavatel je v současné době spojen s údržbou :maintenances_count položek majetku a nemůže být smazán. Aktualizujte prosím údržbu vašeho majetku, aby již tento dodavatel nebyl přiřazen a zkuste to znovu. ',
)
);

View File

@ -22,7 +22,7 @@ return array(
'success' => 'Cyflenwr wedi dileu\'n llwyddiannus.',
'assoc_assets' => 'Ar hyn o bryd mae\'r cyflenwr hwn yn gysylltiedig ag :asset_count asset(s) ac ni ellir ei ddileu. Diweddarwch eich asedau i beidio â chyfeirio\'r cyflenwr hwn mwyach a rhowch cynnig arall arni. ',
'assoc_licenses' => 'Ar hyn o bryd mae\'r cyflenwr hwn yn gysylltiedig â :licenses_count trwydded(au) ac ni ellir eu dileu. Diweddarwch eich trwyddedau i beidio â chyfeirio\'r cyflenwr hwn mwyach a rhoi cynnig arall arni. ',
'assoc_maintenances' => 'Ar hyn o bryd mae\'r cyflenwr hwn yn gysylltiedig â :asset_maintenances_count maint (au) asedau ac ni ellir ei ddileu. Diweddarwch eich cynhaliaeth asedau i beidio â chyfeirio\'r cyflenwr hwn mwyach a rhoi cynnig arall arni. ',
'assoc_maintenances' => 'Ar hyn o bryd mae\'r cyflenwr hwn yn gysylltiedig â :maintenances_count maint (au) asedau ac ni ellir ei ddileu. Diweddarwch eich cynhaliaeth asedau i beidio â chyfeirio\'r cyflenwr hwn mwyach a rhoi cynnig arall arni. ',
)
);

View File

@ -22,7 +22,7 @@ return array(
'success' => 'Leverandøren blev slettet med succes.',
'assoc_assets' => 'Denne placering er i øjeblikket forbundet med :asset_count(s) kan ikke slettes. Opdater dine aktiver for ikke længere at henvise til denne placering, og prøv igen. ',
'assoc_licenses' => 'Denne leverandør er i øjeblikket forbundet med :licenses_count(s) og kan ikke slettes. Opdater dine modeller for ikke længere at henvise til denne leverandør, og prøv igen. ',
'assoc_maintenances' => 'Denne leverandør er i øjeblikket forbundet med :asset_maintenances_count aktiv vedligeholdelse(r) og kan ikke slettes. Opdater din aktiv vedligeholdelse så der ikke længere refereres til denne leverandør og prøv igen. ',
'assoc_maintenances' => 'Denne leverandør er i øjeblikket forbundet med :maintenances_count aktiv vedligeholdelse(r) og kan ikke slettes. Opdater din aktiv vedligeholdelse så der ikke længere refereres til denne leverandør og prøv igen. ',
)
);

View File

@ -22,7 +22,7 @@ return array(
'success' => 'Lieferant wurde erfolgreich gelöscht.',
'assoc_assets' => 'Dieser Lieferant ist derzeit :asset_count Asset(s) zugeordnet und kann nicht gelöscht werden. Bitte aktualisiere Deine Assets, so dass sie nicht mehr auf diesen Lieferant verweisen und versuche es erneut. ',
'assoc_licenses' => 'Dieser Lieferant ist derzeit mit :licenses_count Lizenze(n) verknüpft und kann nicht gelöscht werden. Bitte aktualisiere Deine Lizenzen, so dass sie nicht mehr auf diesen Lieferant verweisen und versuche es erneut. ',
'assoc_maintenances' => 'Dieser Lieferant ist derzeit mit :asset_maintenances_count Asset Wartung(en) verknüpft und kann nicht gelöscht werden. Bitte aktualisiere Deine Wartungsarbeiten, um diesen Lieferanten nicht mehr zu referenzieren und versuche es erneut. ',
'assoc_maintenances' => 'Dieser Lieferant ist derzeit mit :maintenances_count Asset Wartung(en) verknüpft und kann nicht gelöscht werden. Bitte aktualisiere Deine Wartungsarbeiten, um diesen Lieferanten nicht mehr zu referenzieren und versuche es erneut. ',
)
);

View File

@ -22,7 +22,7 @@ return array(
'success' => 'Ο προμηθευτής διαγράφηκε επιτυχώς.',
'assoc_assets' => 'Αυτός ο προμηθευτής συσχετίζεται με τουλάχιστον ένα asset και δεν μπορεί να διαγραφεί. Παρακαλούμε να ενημερώσετε τα asset σας να μην αναφέρονται σε αυτόν τον προμηθευτή και δοκιμάστε ξανά. ',
'assoc_licenses' => 'Αυτός ο προμηθευτής συσχετίζεται επί του παρόντος με :licenses_count άδειες(ες) και δεν μπορεί να διαγραφεί. Ενημερώστε τις άδειες χρήσης σας ώστε να μην αναφέρονται πλέον σε αυτόν τον προμηθευτή και προσπαθήστε ξανά. ',
'assoc_maintenances' => 'Αυτός ο προμηθευτής συσχετίζεται επί του παρόντος με :asset_maintenances_count συντήρηση στοιχείων ενεργητικού και δεν μπορεί να διαγραφεί. Παρακαλούμε ενημερώστε τις συντηρήσεις στοιχείων σας ώστε να μην αναφέρονται πλέον σε αυτόν τον προμηθευτή και προσπαθήστε ξανά. ',
'assoc_maintenances' => 'Αυτός ο προμηθευτής συσχετίζεται επί του παρόντος με :maintenances_count συντήρηση στοιχείων ενεργητικού και δεν μπορεί να διαγραφεί. Παρακαλούμε ενημερώστε τις συντηρήσεις στοιχείων σας ώστε να μην αναφέρονται πλέον σε αυτόν τον προμηθευτή και προσπαθήστε ξανά. ',
)
);

Some files were not shown because too many files have changed in this diff Show More