Skip to content

Commit

Permalink
Merge pull request #640 from wri/release/valiant-velvetseed
Browse files Browse the repository at this point in the history
[RELEASE] Valiant Velvetseed
  • Loading branch information
roguenet authored Jan 9, 2025
2 parents 56647a9 + ea26ca3 commit d65b9d0
Show file tree
Hide file tree
Showing 21 changed files with 316 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public function __invoke(Request $request)
try {
$cacheParameter = $this->getParametersFromRequest($request);
$cacheValue = Redis::get('dashboard:total-section-header|'.$cacheParameter);
$timestampKey = 'dashboard:total-section-header|' . $cacheParameter . ':timestamp';
$lastUpdatedAt = Redis::get($timestampKey);

if (! $cacheValue) {
$frameworks = data_get($request, 'filter.programmes', []);
Expand All @@ -46,7 +48,10 @@ public function __invoke(Request $request)

return (new DelayedJobResource($delayedJob))->additional(['message' => 'Data for total-section-header is being processed']);
} else {
return response()->json(json_decode($cacheValue));
$data = json_decode($cacheValue);
$data->last_updated_at = $lastUpdatedAt;

return response()->json($data);
}
} catch (\Exception $e) {
Log::error('Error during total-header : ' . $e->getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
use App\Helpers\GeometryHelper;
use App\Http\Resources\DelayedJobResource;
use App\Jobs\FixPolygonOverlapJob;
use App\Models\DelayedJob;
use App\Models\DelayedJobProgress;
use App\Models\V2\Sites\CriteriaSite;
use App\Models\V2\Sites\Site;
use App\Models\V2\Sites\SitePolygon;
use App\Services\PolygonService;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
Expand All @@ -25,18 +27,18 @@ public function clipOverlappingPolygonsBySite(string $uuid)
ini_set('memory_limit', '-1');
$user = Auth::user();
$site = Site::isUuid($uuid)->first();
$polygonUuids = GeometryHelper::getSitePolygonsUuids($uuid)->toArray();
$delayedJob = DelayedJobProgress::create([
'processed_content' => 0,
'created_by' => $user->id,
'metadata' => [
'entity_id' => $site->id,
'entity_type' => get_class($site),
'entity_name' => $site->name,
],
'is_acknowledged' => false,
'name' => 'Polygon Fix',
]);
'processed_content' => 0,
'created_by' => $user->id,
'metadata' => [
'entity_id' => $site->id,
'entity_type' => get_class($site),
'entity_name' => $site->name,
],
'is_acknowledged' => false,
'name' => 'Polygon Fix',
]);
$polygonUuids = GeometryHelper::getSitePolygonsUuids($uuid)->toArray();
$job = new FixPolygonOverlapJob($delayedJob->id, $polygonUuids, $user->id);
dispatch($job);

Expand All @@ -62,6 +64,17 @@ public function clipOverlappingPolygonsOfProjectBySite(string $uuid)
return response()->json(['message' => 'No polygons found for the project.'], 204);
}

$delayedJob = DelayedJobProgress::create([
'processed_content' => 0,
'metadata' => [
'entity_id' => $site->id,
'entity_type' => get_class($site),
'entity_name' => $site->name,
],
'created_by' => $user->id,
'is_acknowledged' => false,
'name' => 'Polygon Fix',
]);
$allPolygonUuids = [];
foreach ($polygonUuids as $uuid) {
$polygonOverlappingExtraInfo = CriteriaSite::forCriteria(PolygonService::OVERLAPPING_CRITERIA_ID)
Expand All @@ -84,20 +97,16 @@ public function clipOverlappingPolygonsOfProjectBySite(string $uuid)
$uniquePolygonUuids = array_unique($allPolygonUuids);

if (empty($uniquePolygonUuids)) {
DelayedJob::where('uuid', $delayedJob->uuid)->update([
'status' => DelayedJob::STATUS_FAILED,
'payload' => json_encode(['error' => 'No overlapping polygons found for the project.']),
'status_code' => Response::HTTP_INTERNAL_SERVER_ERROR,
]);

return response()->json(['message' => 'No overlapping polygons found for the project.'], 204);
}

$delayedJob = DelayedJobProgress::create([
'processed_content' => 0,
'metadata' => [
'entity_id' => $site->id,
'entity_type' => get_class($site),
'entity_name' => $site->name,
],
'created_by' => $user->id,
'is_acknowledged' => false,
'name' => 'Polygon Fix',
]);

$job = new FixPolygonOverlapJob($delayedJob->id, $uniquePolygonUuids, $user->id);
dispatch($job);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,42 @@ public function getCriteriaData(Request $request)
return response()->json(['polygon_id' => $uuid, 'criteria_list' => $criteriaList]);
}

public function getCriteriaDataForMultiple(Request $request)
{
$uuids = $request->input('uuids');

if (empty($uuids) || ! is_array($uuids)) {
return response()->json(['error' => 'Invalid or missing UUIDs array'], 400);
}

$response = [];

foreach ($uuids as $uuid) {
$geometry = PolygonGeometry::isUuid($uuid)->first();

if ($geometry === null) {
$response[$uuid] = ['error' => 'Polygon not found for the given UUID'];

continue;
}

$criteriaList = GeometryHelper::getCriteriaDataForPolygonGeometry($geometry);

if (empty($criteriaList)) {
$response[$uuid] = ['error' => 'Criteria data not found for the given polygon ID'];

continue;
}

$response[$uuid] = [
'polygon_id' => $uuid,
'criteria_list' => $criteriaList,
];
}

return response()->json($response);
}

public function getCriteriaDataForMultiplePolygons(array $uuids)
{
$result = [];
Expand Down
2 changes: 1 addition & 1 deletion app/Jobs/Dashboard/RunActiveCountriesTableJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function handle(RunActiveCountriesTableService $runActiveCountriesTableSe

Redis::set('dashboard:active-countries-table|' . $this->cacheParameter, json_encode([
'data' => $response,
]));
]), 'EX', config('cache.ttl.dashboard'));

$delayedJob->update([
'status' => DelayedJob::STATUS_SUCCEEDED,
Expand Down
2 changes: 1 addition & 1 deletion app/Jobs/Dashboard/RunActiveProjectsJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function handle(RunActiveProjectsService $runActiveProjectsService)
]
);
$response = $runActiveProjectsService->runActiveProjectsJob($request);
Redis::set('dashboard:active-projects|' . $this->cacheParameter, json_encode($response));
Redis::set('dashboard:active-projects|' . $this->cacheParameter, json_encode($response), 'EX', config('cache.ttl.dashboard'));


$delayedJob->update([
Expand Down
2 changes: 1 addition & 1 deletion app/Jobs/Dashboard/RunHectaresRestoredJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function handle(RunHectaresRestoredService $runHectaresRestoredService)
]
);
$response = $runHectaresRestoredService->runHectaresRestoredJob($request);
Redis::set('dashboard:indicator/hectares-restoration' . $this->cacheParameter, json_encode($response));
Redis::set('dashboard:indicator/hectares-restoration' . $this->cacheParameter, json_encode($response), 'EX', config('cache.ttl.dashboard'));


$delayedJob->update([
Expand Down
2 changes: 1 addition & 1 deletion app/Jobs/Dashboard/RunJobsCreatedJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public function handle(JobsCreatedService $jobsCreatedService)
]);

$response = $jobsCreatedService->calculateJobsCreated($request);
Redis::set('dashboard:jobs-created|' . $this->cacheParameter, json_encode($response));
Redis::set('dashboard:jobs-created|' . $this->cacheParameter, json_encode($response), 'EX', config('cache.ttl.dashboard'));

$delayedJob->update([
'status' => DelayedJob::STATUS_SUCCEEDED,
Expand Down
2 changes: 1 addition & 1 deletion app/Jobs/Dashboard/RunTopTreesJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function handle(RunTopTreesService $runTopTreesService)
]
);
$response = $runTopTreesService->runTopTreesJob($request);
Redis::set('dashboard:top-trees-planted|' . $this->cacheParameter, json_encode($response));
Redis::set('dashboard:top-trees-planted|' . $this->cacheParameter, json_encode($response), 'EX', config('cache.ttl.dashboard'));


$delayedJob->update([
Expand Down
9 changes: 8 additions & 1 deletion app/Jobs/Dashboard/RunTotalHeaderJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,15 @@ public function handle(RunTotalHeaderService $runTotalHeaderService)
]
);
$response = $runTotalHeaderService->runTotalHeaderJob($request);
Redis::set('dashboard:total-section-header|' . $this->cacheParameter, json_encode($response));

$cacheKey = 'dashboard:total-section-header|' . $this->cacheParameter;
Redis::set($cacheKey, json_encode($response), 'EX', config('cache.ttl.dashboard'));

$timestampKey = $cacheKey . ':timestamp';
Redis::set($timestampKey, now()->toDateTimeString(), 'EX', config('cache.ttl.dashboard'));
$timestampKey = 'dashboard:total-section-header|' . $this->cacheParameter . ':timestamp';
$lastUpdatedAt = Redis::get($timestampKey);
$response->last_updated_at = $lastUpdatedAt;
$delayedJob->update([
'status' => DelayedJob::STATUS_SUCCEEDED,
'payload' => json_encode($response),
Expand Down
2 changes: 1 addition & 1 deletion app/Jobs/Dashboard/RunTreeRestorationGoalJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public function handle(TreeRestorationGoalService $treeRestorationGoalService)
]);

$response = $treeRestorationGoalService->calculateTreeRestorationGoal($request);
Redis::set('dashboard:tree-restoration-goal|' . $this->cacheParameter, json_encode($response));
Redis::set('dashboard:tree-restoration-goal|' . $this->cacheParameter, json_encode($response), 'EX', config('cache.ttl.dashboard'));

$delayedJob->update([
'status' => DelayedJob::STATUS_SUCCEEDED,
Expand Down
2 changes: 1 addition & 1 deletion app/Jobs/Dashboard/RunVolunteersAverageJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function handle(RunVolunteersAverageService $runVolunteersAverageService)
]
);
$response = $runVolunteersAverageService->runVolunteersAverageJob($request);
Redis::set('dashboard:volunteers-survival-rate|' . $this->cacheParameter, json_encode($response));
Redis::set('dashboard:volunteers-survival-rate|' . $this->cacheParameter, json_encode($response), 'EX', config('cache.ttl.dashboard'));


$delayedJob->update([
Expand Down
18 changes: 17 additions & 1 deletion app/Models/V2/Projects/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,22 @@ public function sitePolygons(): HasManyThrough
)->active();
}

public function approvedSitePolygons(): HasManyThrough
{
return $this->hasManyThrough(
SitePolygon::class,
Site::class,
'project_id',
'site_id',
'id',
'uuid'
)
->whereHas('site', function ($query) {
$query->whereIn('status', Site::$approvedStatuses);
})
->active();
}

public function treeSpecies()
{
return $this->morphMany(TreeSpecies::class, 'speciesable');
Expand Down Expand Up @@ -615,6 +631,6 @@ public function getTotalSitePolygonsAttribute()

public function getTotalHectaresRestoredSumAttribute(): float
{
return round($this->sitePolygons->where('status', 'approved')->sum('calc_area'));
return $this->approvedSitePolygons->where('status', 'approved')->sum('calc_area');
}
}
11 changes: 6 additions & 5 deletions app/Validators/Extensions/Polygons/NotOverlapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,15 @@ public static function getIntersectionData(string $polygonUuid): array

$mainPolygonArea = PolygonGeometry::where('uuid', $polygonUuid)
->value(DB::raw('ST_Area(geom)'));

$extra_info = $intersects
->filter(fn ($intersect) => $intersect->intersects)
->map(function ($intersect) use ($mainPolygonArea) {
->filter(function ($intersect) {
return $intersect->intersects && $intersect->intersection_area > 1e-10;
})
->map(function ($intersect) use ($mainPolygonArea, $sitePolygon) {
$minArea = min($mainPolygonArea, $intersect->area);
$percentage = $minArea > 0
? round(($intersect->intersection_area / $minArea) * 100, 2)
: 100;
? round(($intersect->intersection_area / $minArea) * 100, 2)
: 100;

return [
'poly_uuid' => $intersect->uuid,
Expand Down
14 changes: 14 additions & 0 deletions config/cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,18 @@

'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'),

/*
|--------------------------------------------------------------------------
| Cache Timeout Values
|--------------------------------------------------------------------------
|
| Here you may define the cache timeout values for different sections
| of the application. These values can be used in any controllers
| to set the time-to-live (TTL) for cached items.
|
*/

'ttl' => [
'dashboard' => 86400, // 24 hours
]
];
37 changes: 37 additions & 0 deletions openapi-src/V2/definitions/V2TerrafundCriteriaDataMultiple.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
type: object
additionalProperties:
oneOf:
- type: object
properties:
polygon_id:
type: string
description: The ID of the polygon
criteria_list:
type: array
description: List of validation criteria
items:
type: object
properties:
criteria_id:
type: integer
description: The ID of the criteria
latest_created_at:
type: string
format: date-time
description: The latest created at timestamp of the criteria
valid:
type: integer
description: Indicates if the criteria is valid or not (1 for valid, 0 for invalid)
extra_info:
type: object
description: Extra information about the polygon validation
required:
- polygon_id
- criteria_list
- type: object
properties:
error:
type: string
description: Error message if the polygon or criteria data is not found
required:
- error
6 changes: 4 additions & 2 deletions openapi-src/V2/definitions/_index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ EntityFormCreate:
EntityFormUpdate:
$ref: './EntityFormUpdate.yml'
EntityFormRead:
$ref: './EntityFormRead.yml'
$ref: './EntityFormRead.yml'
UserRead:
$ref: './UserRead.yml'
UserReadAll:
Expand Down Expand Up @@ -276,6 +276,8 @@ AuditStatusResponse:
$ref: './AuditStatusResponse.yml'
V2TerrafundCriteriaData:
$ref: './V2TerrafundCriteriaData.yml'
V2TerrafundCriteriaDataMultiple:
$ref: './V2TerrafundCriteriaDataMultiple.yml'
V2TerrafundCriteriaSite:
$ref: './V2TerrafundCriteriaSite.yml'
DashboardProjectAvailableResponse:
Expand Down Expand Up @@ -312,7 +314,7 @@ DashboardTreesUnderRestorationActual:
$ref: './DashboardTreesUnderRestorationActual.yml'
DashboardGetProjectsResponse:
$ref: './DashboardGetProjectsResponse.yml'
DashboardGetProjectsData:
DashboardGetProjectsData:
$ref: './DashboardGetProjectsData.yml'
DashboardGetPolygonStatusResponse:
$ref: './DashboardGetPolygonStatusResponse.yml'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ responses:
'200':
description: Successful response
schema:
$ref: '../../definitions/_index.yml#/V2TerrafundCriteriaData'
$ref: '../../definitions/_index.yml#/V2TerrafundCriteriaData'
Loading

0 comments on commit d65b9d0

Please sign in to comment.