Entrega dashboard e correccoes transversais preservando Ofertas instalado
tests / ci (push) Waiting to run
tests / ci (push) Waiting to run
This commit is contained in:
@@ -68,7 +68,17 @@ final class FundingProgrammes
|
||||
/** @param array<string,mixed> $filters */
|
||||
public function catalogueQuery(array $filters): Builder
|
||||
{
|
||||
Validator::make($filters, ['q' => 'nullable|string|max:150', 'state' => 'nullable|in:open,closed,upcoming,unknown', 'certainty' => 'nullable|in:include_unknown,documented',
|
||||
'sector' => ['nullable', 'integer', Rule::in(Sector::choices()->whereNotNull('published_at')->pluck('id')->all())], 'need' => ['nullable', Rule::in(array_keys(FundingInstitutionDetails::NEEDS))], 'include_historical' => 'nullable|boolean'])->validate();
|
||||
$filters = app(InvestmentGeography::class)->interestSelection($filters);
|
||||
$query = $this->publicQuery();
|
||||
if (! empty($filters['q'])) {
|
||||
$term = '%'.str_replace(['\\', '%', '_'], ['\\\\', '\\%', '\\_'], $filters['q']).'%';
|
||||
$query->where(fn ($q) => $q->whereRaw("v.payload->>'title' ilike ?", [$term])->orWhereRaw("v.payload->>'summary' ilike ?", [$term])->orWhereRaw("(v.payload->'aliases')::text ilike ?", [$term])->orWhereRaw("EXISTS (SELECT 1 FROM jsonb_array_elements(COALESCE(v.payload->'locations','[]'::jsonb)) l WHERE l->>'label' ilike ? OR l->>'address' ilike ? OR l->>'location_text' ilike ?)", [$term, $term, $term]));
|
||||
}
|
||||
if (! empty($filters['kind'])) {
|
||||
$query->whereRaw("v.payload->>'kind' = ?", [$filters['kind']]);
|
||||
}
|
||||
app(FundingInstitutionDetails::class)->applyFilters($query, $filters);
|
||||
$includeUnknown = ($filters['certainty'] ?? 'include_unknown') === 'include_unknown';
|
||||
if (! empty($filters['sector'])) {
|
||||
@@ -94,22 +104,43 @@ final class FundingProgrammes
|
||||
});
|
||||
}
|
||||
if (! empty($filters['state'])) {
|
||||
$today = today()->toDateString();
|
||||
$state = $filters['state'];
|
||||
if ($state === 'unknown') {
|
||||
$query->whereRaw("(jsonb_array_length(v.payload->'windows') = 0 OR EXISTS (SELECT 1 FROM jsonb_array_elements(v.payload->'windows') w WHERE w->>'mode' = 'unknown'))");
|
||||
} elseif ($state === 'closed') {
|
||||
$query->whereRaw("EXISTS (SELECT 1 FROM jsonb_array_elements(v.payload->'windows') w WHERE w->>'mode' = 'closed' OR (w->>'mode' = 'dated' AND w->>'end_on' < ?))", [$today]);
|
||||
} elseif ($state === 'upcoming') {
|
||||
$query->whereRaw("EXISTS (SELECT 1 FROM jsonb_array_elements(v.payload->'windows') w WHERE w->>'mode' = 'dated' AND w->>'start_on' > ?)", [$today]);
|
||||
} else {
|
||||
$query->whereRaw("EXISTS (SELECT 1 FROM jsonb_array_elements(v.payload->'windows') w WHERE w->>'mode' IN ('dated','rolling') AND COALESCE(NULLIF(w->>'start_on',''),?) <= ? AND COALESCE(NULLIF(w->>'end_on',''),?) >= ?)", [$today, $today, $today, $today]);
|
||||
}
|
||||
[$windowSql, $windowBindings] = $this->windowFilter($filters);
|
||||
$query->whereRaw("EXISTS (SELECT 1 FROM jsonb_array_elements(COALESCE(v.payload->'windows','[]'::jsonb)) w WHERE ".$windowSql.')', $windowBindings);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/** Window dates and geographical scope concern the same documented window.
|
||||
* @param array<string,mixed> $filters
|
||||
* @return array{literal-string,list<mixed>}
|
||||
*/
|
||||
private function windowFilter(array $filters): array
|
||||
{
|
||||
$today = today()->toDateString();
|
||||
$state = $filters['state'];
|
||||
$bindings = [];
|
||||
if ($state === 'unknown') $sql = "w->>'mode' = 'unknown'";
|
||||
elseif ($state === 'closed') { $sql = "(w->>'mode' = 'closed' OR (w->>'mode' = 'dated' AND w->>'end_on' < ?))"; $bindings = [$today]; }
|
||||
elseif ($state === 'upcoming') { $sql = "w->>'mode' = 'dated' AND w->>'start_on' > ?"; $bindings = [$today]; }
|
||||
else { $sql = "w->>'mode' IN ('dated','rolling') AND COALESCE(NULLIF(w->>'start_on',''),?) <= ? AND COALESCE(NULLIF(w->>'end_on',''),?) >= ?"; $bindings = [$today, $today, $today, $today]; }
|
||||
if (! empty($filters['territory']) && ($filters['location_mode'] ?? '') !== 'physical') {
|
||||
$path = array_column(app(InvestmentGeography::class)->path($filters['territory']), 'id');
|
||||
$window = ["EXISTS (SELECT 1 FROM jsonb_array_elements(COALESCE(w->'territory_paths','[]'::jsonb)) t WHERE t @> ?::jsonb)"];
|
||||
$scopeBindings = [json_encode([['id' => $filters['territory']]], JSON_THROW_ON_ERROR)];
|
||||
foreach ($path as $id) { $window[] = "w->'territory_ids' @> ?::jsonb"; $scopeBindings[] = json_encode([$id], JSON_THROW_ON_ERROR); }
|
||||
$parent = ["v.payload->>'coverage'='national'", "v.payload->'territory_ancestor_ids' @> ?::jsonb"];
|
||||
$scopeBindings[] = json_encode([$filters['territory']], JSON_THROW_ON_ERROR);
|
||||
foreach ($path as $id) { $parent[] = "v.payload->'territory_ids' @> ?::jsonb"; $scopeBindings[] = json_encode([$id], JSON_THROW_ON_ERROR); }
|
||||
if (($filters['certainty'] ?? 'include_unknown') === 'include_unknown') $parent[] = "v.payload->>'coverage'='unknown'";
|
||||
$scope = "(w->>'coverage'='national' OR (w->>'coverage'='territorial' AND (".implode(' OR ', $window).")) OR (w->>'coverage'='programme' AND (".implode(' OR ', $parent).')))';
|
||||
if (($filters['certainty'] ?? 'include_unknown') === 'include_unknown') $scope = '('.$scope." OR w->>'coverage'='unknown')";
|
||||
$sql = '('.$sql.') AND '.$scope;
|
||||
$bindings = [...$bindings, ...$scopeBindings];
|
||||
}
|
||||
return [$sql, $bindings];
|
||||
}
|
||||
|
||||
/** @param array<string,mixed> $record
|
||||
* @param array<string,mixed> $filters
|
||||
* @return array<string,string> */
|
||||
|
||||
Reference in New Issue
Block a user