diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index f7dd439e28..8f87728f34 100644 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -162,6 +162,38 @@ class SettingsController extends Controller return redirect()->back()->withInput()->withErrors($setting->getErrors()); } + /** + * Stream a CSV of every location-scoping FMCS mismatch. + * + * This endpoint runs the full walk (artisan=true) and streams + * the same table columns the CLI command prints, as CSV. + */ + public function downloadLocationScopingReport(): \Symfony\Component\HttpFoundation\StreamedResponse + { + $mismatched = Helper::test_locations_fmcs(true); + + $filename = 'location-scoping-mismatches-' . date('Y-m-d') . '.csv'; + + return response()->streamDownload(function () use ($mismatched) { + $out = fopen('php://output', 'w'); + fputcsv($out, [ + 'Type', + 'ID', + 'Name', + 'Checkout Type', + 'Company IDs', + 'Item Companies', + 'Item Location', + 'Location Company', + 'Location Company ID', + ]); + foreach ($mismatched as $row) { + fputcsv($out, $row); + } + fclose($out); + }, $filename, ['Content-Type' => 'text/csv']); + } + /** * Return a form to allow a super admin to update settings. * diff --git a/resources/lang/en-US/admin/settings/general.php b/resources/lang/en-US/admin/settings/general.php index 59872a0f4b..0544e20e0d 100644 --- a/resources/lang/en-US/admin/settings/general.php +++ b/resources/lang/en-US/admin/settings/general.php @@ -280,6 +280,7 @@ return [ 'scope_locations_fmcs_check_button' => 'Check Compatibility', 'scope_locations_fmcs_test_needed' => 'Please Check Compatibility to enable this', 'scope_locations_fmcs_support_disabled_text' => 'This option is disabled because you have conflicting locations set for :count or more items.', + 'scope_locations_fmcs_download_report' => 'Download mismatch report (CSV)', 'null_company_is_floater_text' => 'Treat items and users without company associations as floaters', 'null_company_is_floater_help_text' => 'When disabled, items can only be checked out to targets without a company association if the item also has no company - null is treated as its own pseudo-company. When enabled, items from any company can be checked out to targets with no company assignment.', 'show_in_model_list' => 'Show in Model Dropdowns', diff --git a/resources/views/livewire/location-scope-check.blade.php b/resources/views/livewire/location-scope-check.blade.php index f6c714897b..b2ad4be0e0 100644 --- a/resources/views/livewire/location-scope-check.blade.php +++ b/resources/views/livewire/location-scope-check.blade.php @@ -12,4 +12,18 @@ @endif

+ + {{-- Download-full-report link. Shown only after the enable-check + has run AND found mismatches. The endpoint runs the full walk of + Helper::test_locations_fmcs and streams a CSV, so expect it to + take longer than the enable-check on large datasets since it + doesn't early-bail. --}} + @if ($is_tested && count($mismatched) > 0) + + + {{ trans('admin/settings/general.scope_locations_fmcs_download_report') }} + + @endif \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index d27adbef0c..0a52443b56 100644 --- a/routes/web.php +++ b/routes/web.php @@ -230,6 +230,9 @@ Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'authorize:superuser Route::post('settings', [SettingsController::class, 'postSettings']) ->name('settings.general.save'); + Route::get('settings/location-scoping-report.csv', [SettingsController::class, 'downloadLocationScopingReport']) + ->name('settings.general.location_scoping_report'); + Route::get('branding', [SettingsController::class, 'getBranding']) ->name('settings.branding.index') ->breadcrumbs(fn (Trail $trail) => $trail->parent('settings.index')