@@ -5,7 +5,9 @@ namespace App\Http\Controllers;
|
||||
use App\Models\SupplierEvaluation;
|
||||
use App\Models\SupplierImprovement;
|
||||
use App\Models\User;
|
||||
use App\Services\AdministrativeGeography;
|
||||
use App\Services\SupplierEvaluationWorkflow;
|
||||
use App\Services\SupplierGeography;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -16,6 +18,22 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class SupplierImprovementReportController extends Controller
|
||||
{
|
||||
private function actor(Request $request): User
|
||||
{
|
||||
$actor = $request->user('web');
|
||||
abort_unless($actor instanceof User, 403);
|
||||
|
||||
return $actor;
|
||||
}
|
||||
|
||||
/** @param array<string,mixed> $filters
|
||||
* @return array<string,mixed>|null
|
||||
*/
|
||||
private function territory(array $filters): ?array
|
||||
{
|
||||
return empty($filters['location']) ? null : app(AdministrativeGeography::class)->describe(['country' => 'MZ', 'catalogue' => config('geography.source_sha256'), 'record_id' => $filters['location']]);
|
||||
}
|
||||
|
||||
private function snapshot(\Closure $read): mixed
|
||||
{
|
||||
if (DB::getDriverName() === 'pgsql' && DB::transactionLevel() !== 0) {
|
||||
@@ -34,12 +52,12 @@ class SupplierImprovementReportController extends Controller
|
||||
/** @return array<string,mixed> */
|
||||
private function filters(Request $request): array
|
||||
{
|
||||
$actor = app(SupplierEvaluationWorkflow::class)->reader($request->user());
|
||||
$actor = app(SupplierEvaluationWorkflow::class)->reader($this->actor($request));
|
||||
$request->setUserResolver(fn () => $actor);
|
||||
abort_unless(Schema::hasTable('supplier_improvements'), 503, 'A instalação das medidas de melhoria ainda não está concluída.');
|
||||
$filters = $request->validate(['supplier_id' => 'nullable|integer|min:1', 'responsible_id' => 'nullable|integer|min:1',
|
||||
'status' => 'nullable|in:open,review,returned,closed', 'from' => 'nullable|date_format:Y-m-d', 'to' => 'nullable|date_format:Y-m-d',
|
||||
'overdue' => 'nullable|in:1', 'search' => 'nullable|string|max:200']);
|
||||
'overdue' => 'nullable|in:1', 'search' => 'nullable|string|max:200', 'location' => 'nullable|string|regex:/^[0-9]+$/D|max:20']);
|
||||
if (! empty($filters['from']) && ! empty($filters['to']) && $filters['to'] < $filters['from']) {
|
||||
throw ValidationException::withMessages(['to' => 'O fim do intervalo deve ser igual ou posterior ao início.']);
|
||||
}
|
||||
@@ -52,7 +70,11 @@ class SupplierImprovementReportController extends Controller
|
||||
*/
|
||||
private function query(Request $request, array $filters, string $today): Builder
|
||||
{
|
||||
$query = SupplierImprovement::query()->visibleTo($request->user());
|
||||
$query = SupplierImprovement::query()->visibleTo($this->actor($request));
|
||||
if (! empty($filters['location'])) {
|
||||
$suppliers = app(SupplierGeography::class)->matching($filters['location'])->select('id');
|
||||
$query->whereHas('evaluation', fn ($evaluation) => $evaluation->whereIn('supplier_id', $suppliers));
|
||||
}
|
||||
if (! empty($filters['supplier_id'])) {
|
||||
$query->whereHas('evaluation', fn ($q) => $q->where('supplier_id', $filters['supplier_id']));
|
||||
}
|
||||
@@ -81,7 +103,7 @@ class SupplierImprovementReportController extends Controller
|
||||
*/
|
||||
private function records(Builder $query, Request $request): Builder
|
||||
{
|
||||
return $query->with(['evaluation:id,supplier_id,supplier_snapshot,revision', 'responsible' => fn ($q) => $q->where('tenant_id', $request->user()->tenant_id)->select(['id', 'name'])]);
|
||||
return $query->with(['evaluation:id,supplier_id,supplier_snapshot,revision', 'responsible' => fn ($q) => $q->where('tenant_id', $this->actor($request)->tenant_id)->select(['id', 'name'])]);
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
@@ -99,17 +121,17 @@ class SupplierImprovementReportController extends Controller
|
||||
$props = $this->snapshot(function () use ($request): array {
|
||||
$filters = $this->filters($request);
|
||||
$today = today()->toDateString();
|
||||
$all = SupplierImprovement::query()->visibleTo($request->user());
|
||||
$all = SupplierImprovement::query()->visibleTo($this->actor($request));
|
||||
$query = $this->query($request, $filters, $today);
|
||||
$counts = (clone $query)->selectRaw('status, COUNT(*) AS count')->groupBy('status')->pluck('count', 'status')->map(fn ($n) => (int) $n);
|
||||
$overdue = (clone $query)->where('status', '!=', 'closed')->where('due_on', '<', $today)->count();
|
||||
// Choices derive only from visible measures, including prior revisions and former assignees.
|
||||
$evaluations = SupplierEvaluation::query()->visibleTo($request->user())->whereIn('id', (clone $all)->select('supplier_evaluation_id'))->orderByDesc('id')->get(['supplier_id', 'supplier_snapshot']);
|
||||
$evaluations = SupplierEvaluation::query()->visibleTo($this->actor($request))->whereIn('id', (clone $all)->select('supplier_evaluation_id'))->orderByDesc('id')->get(['supplier_id', 'supplier_snapshot']);
|
||||
|
||||
return ['filters' => $filters, 'today' => $today, 'generatedAt' => now()->toIso8601String(), 'counts' => $counts, 'overdue' => $overdue,
|
||||
return ['filters' => $filters, 'geographyEnabled' => app(AdministrativeGeography::class)->enabled(), 'geographyFilter' => $this->territory($filters), 'today' => $today, 'generatedAt' => now()->toIso8601String(), 'counts' => $counts, 'overdue' => $overdue,
|
||||
'records' => $this->records($query, $request)->orderBy('due_on')->orderBy('id')->paginate(25)->withQueryString()->through(fn (SupplierImprovement $m) => $this->row($m, $today)),
|
||||
'suppliers' => $evaluations->map(fn (SupplierEvaluation $e) => ['id' => $e->supplier_id, 'name' => $e->supplier_snapshot['name']])->unique('id')->values(),
|
||||
'responsibles' => User::query()->where('tenant_id', $request->user()->tenant_id)->whereIn('id', (clone $all)->select('responsible_id'))->orderBy('name')->get(['id', 'name'])];
|
||||
'responsibles' => User::query()->where('tenant_id', $this->actor($request)->tenant_id)->whereIn('id', (clone $all)->select('responsible_id'))->orderBy('name')->get(['id', 'name'])];
|
||||
});
|
||||
Inertia::encryptHistory();
|
||||
$response = Inertia::render('reports/supplier-improvements', $props)->toResponse($request);
|
||||
@@ -121,6 +143,9 @@ class SupplierImprovementReportController extends Controller
|
||||
public function csv(Request $request): Response
|
||||
{
|
||||
$filters = $this->filters($request);
|
||||
if (! empty($filters['location'])) {
|
||||
app(SupplierGeography::class)->matching($filters['location']);
|
||||
}
|
||||
$text = fn (?string $value) => preg_match('/^[\s]*[=+\-@]|^[\t\r\n]/u', $value ?? '') ? "'".$value : ($value ?? '');
|
||||
|
||||
return response()->streamDownload(fn () => $this->snapshot(function () use ($request, $filters, $text) {
|
||||
@@ -133,7 +158,12 @@ class SupplierImprovementReportController extends Controller
|
||||
}
|
||||
fwrite($out, "\xEF\xBB\xBF");
|
||||
fputcsv($out, ['Medidas de melhoria de fornecedores', 'Consulta', now()->toIso8601String(), 'Data de referência', $today], ';', '"', '');
|
||||
fputcsv($out, ['Filtros', $text(json_encode($filters, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR))], ';', '"', '');
|
||||
$exportFilters = $filters;
|
||||
if (! empty($filters['location'])) {
|
||||
$territory = $this->territory($filters);
|
||||
$exportFilters['localizacao_actual_da_ficha'] = implode(' / ', array_column($territory['path'] ?? [], 'name'));
|
||||
}
|
||||
fputcsv($out, ['Filtros', $text(json_encode($exportFilters, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR))], ';', '"', '');
|
||||
fputcsv($out, ['Medida', 'Fornecedor preservado', 'Avaliação', 'Revisão', 'Título', 'Objectivo', 'Responsável', 'Prazo', 'Estado', 'Prazo ultrapassado', 'Versão', 'Resultado', 'Evidência', 'Última conferência', 'Conferida em', 'Avaliação e acompanhamento', 'Relatório individual'], ';', '"', '');
|
||||
foreach ($this->records($this->query($request, $filters, $today), $request)->lazyById(200) as $m) {
|
||||
$row = $this->row($m, $today);
|
||||
|
||||
Reference in New Issue
Block a user