FMCS/Validation: Fixed #19166 - translate error messages on FMCS fail

This commit is contained in:
snipe
2026-06-10 12:44:46 +01:00
parent 66bf6275b8
commit 6a0ec69451
10 changed files with 100 additions and 19 deletions
@@ -77,7 +77,17 @@ class AccessoryCheckoutController extends Controller
}
if ($mismatch) {
return redirect()->back()->with('error', trans('general.error_user_company'));
$targetType = match (class_basename($target)) {
'User' => trans('general.user'),
'Location' => trans('general.location'),
default => trans('general.asset'),
};
return redirect()->back()->with('error', trans('general.error_checkout_company_mismatch', [
'item' => trans('general.accessory').' "'.$accessory->name.'"',
'item_company' => $accessory->company?->name ?? trans('general.unassigned'),
'target' => $targetType.' "'.($target->name ?? $target->username ?? $target->id).'"',
]));
}
}
@@ -215,8 +215,12 @@ class LocationsController extends Controller
if (Setting::getSettings()->scope_locations_fmcs) {
$location->company_id = Company::getIdForCurrentUser($request->input('company_id'));
// check if parent is set and has a different company
if ($location->parent_id && Location::find($location->parent_id)->company_id != $location->company_id) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'different company than parent'));
if ($location->parent_id && ($parent = Location::find($location->parent_id)) && $parent->company_id != $location->company_id) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.error_location_parent_company', [
'parent' => $parent->name,
'parent_company' => $parent->company?->name ?? trans('general.unassigned'),
'location_company' => $location->company?->name ?? trans('general.unassigned'),
])));
}
}
@@ -307,12 +311,22 @@ class LocationsController extends Controller
if (Setting::getSettings()->scope_locations_fmcs) {
$location->company_id = Company::getIdForCurrentUser($request->input('company_id'));
// check if there are related objects with different company
if (Helper::test_locations_fmcs(false, $id, $location->company_id)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'error scoped locations'));
if ($mismatched = Helper::test_locations_fmcs(false, $id, $location->company_id)) {
$first = $mismatched[0];
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.error_location_scoped_items', [
'item_type' => trans('general.'.strtolower($first[0])),
'item_name' => $first[2],
'item_company' => $first[5] ?? trans('general.unassigned'),
])));
}
// check if parent is set and has a different company
if ($location->parent_id && Location::find($location->parent_id)->company_id != $location->company_id) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'different company than parent'));
if ($location->parent_id && ($parent = Location::find($location->parent_id)) && $parent->company_id != $location->company_id) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.error_location_parent_company', [
'parent' => $parent->name,
'parent_company' => $parent->company?->name ?? trans('general.unassigned'),
'location_company' => $location->company?->name ?? trans('general.unassigned'),
])));
}
} else {
$location->company_id = $request->input('company_id');
@@ -131,7 +131,17 @@ class AssetCheckoutController extends Controller
: (int) $target->company_id !== (int) $asset->company_id);
if ($mismatch) {
return redirect()->route('hardware.checkout.create', $asset)->with('error', trans('general.error_user_company'));
$targetType = match (class_basename($target)) {
'User' => trans('general.user'),
'Location' => trans('general.location'),
default => trans('general.asset'),
};
return redirect()->route('hardware.checkout.create', $asset)->with('error', trans('general.error_checkout_company_mismatch', [
'item' => trans('general.asset').' "'.($asset->name ?? $asset->asset_tag).'"',
'item_company' => $asset->company?->name ?? trans('general.unassigned'),
'target' => $targetType.' "'.($target->name ?? $target->username ?? $target->id).'"',
]));
}
}
@@ -105,7 +105,11 @@ class ComponentCheckoutController extends Controller
$asset = Asset::find($request->input('asset_id'));
if ((Setting::getSettings()->full_multiple_companies_support) && $component->company_id !== $asset->company_id) {
return redirect()->route('components.checkout.show', $componentId)->with('error', trans('general.error_user_company'));
return redirect()->route('components.checkout.show', $componentId)->with('error', trans('general.error_checkout_company_mismatch', [
'item' => trans('general.component').' "'.$component->name.'"',
'item_company' => $component->company?->name ?? trans('general.unassigned'),
'target' => trans('general.asset').' "'.($asset->name ?? $asset->asset_tag).'"',
]));
}
$component->checkout_qty = $request->input('assigned_qty');
@@ -102,7 +102,11 @@ class ConsumableCheckoutController extends Controller
&& $consumable->company_id
&& ! $user->canReceiveFromCompany($consumable->company_id)
) {
return redirect()->back()->with('error', trans('general.error_user_company'));
return redirect()->back()->with('error', trans('general.error_checkout_company_mismatch', [
'item' => trans('general.consumable').' "'.$consumable->name.'"',
'item_company' => $consumable->company?->name ?? trans('general.unassigned'),
'target' => trans('general.user').' "'.$user->username.'"',
]));
}
// Update the consumable data
@@ -104,13 +104,21 @@ class LicenseCheckoutController extends Controller
? ! Setting::getSettings()->null_company_is_floater
: ($license->company_id !== $fmcsTarget->company_id);
if ($mismatch) {
return redirect()->route('licenses.index')->with('error', trans('general.error_user_company'));
return redirect()->route('licenses.index')->with('error', trans('general.error_checkout_company_mismatch', [
'item' => trans('general.license').' "'.$license->name.'"',
'item_company' => $license->company?->name ?? trans('general.unassigned'),
'target' => trans('general.asset').' "'.($fmcsTarget->name ?? $fmcsTarget->asset_tag).'"',
]));
}
}
} elseif ($request->filled('assigned_to')) {
$fmcsTarget = User::find($request->input('assigned_to'));
if ($fmcsTarget && $license->company_id && ! $fmcsTarget->canReceiveFromCompany($license->company_id)) {
return redirect()->route('licenses.index')->with('error', trans('general.error_user_company'));
return redirect()->route('licenses.index')->with('error', trans('general.error_checkout_company_mismatch', [
'item' => trans('general.license').' "'.$license->name.'"',
'item_company' => $license->company?->name ?? trans('general.unassigned'),
'target' => trans('general.user').' "'.$fmcsTarget->username.'"',
]));
}
}
}
+20 -6
View File
@@ -95,8 +95,12 @@ class LocationsController extends Controller
if (Setting::getSettings()->scope_locations_fmcs) {
$location->company_id = Company::getIdForCurrentUser($request->input('company_id'));
// check if parent is set and has a different company
if ($location->parent_id && Location::find($location->parent_id)->company_id != $location->company_id) {
return redirect()->back()->withInput()->withInput()->with('error', 'different company than parent');
if ($location->parent_id && ($parent = Location::find($location->parent_id)) && $parent->company_id != $location->company_id) {
return redirect()->back()->withInput()->with('error', trans('general.error_location_parent_company', [
'parent' => $parent->name,
'parent_company' => $parent->company?->name ?? trans('general.unassigned'),
'location_company' => $location->company?->name ?? trans('general.unassigned'),
]));
}
} else {
$location->company_id = $request->input('company_id');
@@ -175,12 +179,22 @@ class LocationsController extends Controller
if (Setting::getSettings()->scope_locations_fmcs) {
$location->company_id = Company::getIdForCurrentUser($request->input('company_id'));
// check if there are related objects with different company
if (Helper::test_locations_fmcs(false, $location->id, $location->company_id)) {
return redirect()->back()->withInput()->withInput()->with('error', 'error scoped locations');
if ($mismatched = Helper::test_locations_fmcs(false, $location->id, $location->company_id)) {
$first = $mismatched[0];
return redirect()->back()->withInput()->with('error', trans('general.error_location_scoped_items', [
'item_type' => trans('general.'.strtolower($first[0])),
'item_name' => $first[2],
'item_company' => $first[5] ?? trans('general.unassigned'),
]));
}
// check if parent is set and has a different company
if ($location->parent_id && Location::find($location->parent_id)->company_id != $location->company_id) {
return redirect()->back()->withInput()->withInput()->with('error', 'different company than parent');
if ($location->parent_id && ($parent = Location::find($location->parent_id)) && $parent->company_id != $location->company_id) {
return redirect()->back()->withInput()->with('error', trans('general.error_location_parent_company', [
'parent' => $parent->name,
'parent_company' => $parent->company?->name ?? trans('general.unassigned'),
'location_company' => $location->company?->name ?? trans('general.unassigned'),
]));
}
} else {
$location->company_id = $request->input('company_id');
@@ -349,6 +349,20 @@ class ValidationServiceProvider extends ServiceProvider
return in_array($value, $options);
});
Validator::replacer('fmcs_location', function ($message, $attribute, $rule, $parameters, $validator) {
$locationId = $validator->getData()[$attribute] ?? null;
$location = $locationId ? Location::find($locationId) : null;
return str_replace(
[':location', ':location_company'],
[
$location?->name ?? '?',
$location?->company?->name ?? trans('general.unassigned'),
],
$message
);
});
// Validates that the company of the validated object matches the company of the location in case of scoped locations
Validator::extend('fmcs_location', function ($attribute, $value, $parameters, $validator) {
$settings = Setting::getSettings();
+3
View File
@@ -587,6 +587,9 @@ return [
'error_user_company' => 'Checkout target company and asset company do not match',
'error_user_company_multiple' => 'One or more of the checkout target company and asset company do not match',
'error_user_company_accept_view' => 'An Asset assigned to you belongs to a different company so you can\'t accept nor deny it, please check with your manager',
'error_checkout_company_mismatch' => ':item cannot be checked out to :target — :item belongs to :item_company',
'error_location_scoped_items' => 'This location cannot be saved. :item_type ":item_name" (Company: :item_company) does not match this location\'s company.',
'error_location_parent_company' => 'Parent location ":parent" belongs to :parent_company, but this location belongs to :location_company.',
'error_assets_already_checked_out' => 'One or more of the assets are already checked out',
'assigned_assets_removed' => 'The following were removed from the selected assets because they are already checked out',
'unassigned_assets_removed' => 'The following were removed from the selected assets because they are not currently checked out',
+1 -1
View File
@@ -174,7 +174,7 @@ return [
'ulid' => 'The :attribute field must be a valid ULID.',
'uuid' => 'The :attribute field must be a valid UUID.',
'valid_css_color' => 'The :attribute field must be a valid CSS color (hex, rgb, rgba, hsl, or hsla).',
'fmcs_location' => 'Full multiple company support and location scoping is enabled in the Admin Settings, and the selected location and selected company are not compatible.',
'fmcs_location' => 'Location ":location" belongs to :location_company, which does not match the selected company.',
'is_unique_across_company_and_location' => 'The :attribute must be unique within the selected company and location.',
/*