Skip to content

Commit

Permalink
Merge pull request #237 from wri/feat/TM-617/626/627/658_tree_restora…
Browse files Browse the repository at this point in the history
…tion_and_export

[TM-617, 626, 627, 658] feat: add tree restoration controller and export csv
  • Loading branch information
cesarLima1 authored Jun 6, 2024
2 parents d13cb96 + b78b05b commit 4846c75
Show file tree
Hide file tree
Showing 38 changed files with 1,816 additions and 58 deletions.
106 changes: 53 additions & 53 deletions app/Helpers/GeometryHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,46 @@

class GeometryHelper
{
public static function getPolygonsBbox($polygonsIds)
public function centroidOfProject($projectUuid)
{
$envelopes = PolygonGeometry::whereIn('uuid', $polygonsIds)
->selectRaw('ST_ASGEOJSON(ST_Envelope(geom)) as envelope')
$project = Project::where('uuid', $projectUuid)->first();

if (! $project) {
return null;
}
$polyIds = $project->sitePolygons()->pluck('poly_id')->toArray();

if (empty($polyIds)) {
return null;
}

$centroids = PolygonGeometry::selectRaw('ST_AsGeoJSON(ST_Centroid(geom)) AS centroid')
->whereIn('uuid', $polyIds)
->get();

$maxX = $maxY = PHP_INT_MIN;
$minX = $minY = PHP_INT_MAX;
if ($centroids->isEmpty()) {
return null; // Return null if no centroids are found
}

foreach ($envelopes as $envelope) {
$geojson = json_decode($envelope->envelope);
$coordinates = $geojson->coordinates[0];
$centroidCount = $centroids->count();
$totalLatitude = 0;
$totalLongitude = 0;

foreach ($coordinates as $point) {
$x = $point[0];
$y = $point[1];
$maxX = max($maxX, $x);
$minX = min($minX, $x);
$maxY = max($maxY, $y);
$minY = min($minY, $y);
}
foreach ($centroids as $centroid) {
$centroidData = json_decode($centroid->centroid, true);
$totalLatitude += $centroidData['coordinates'][1];
$totalLongitude += $centroidData['coordinates'][0];
}

$bboxCoordinates = [$minX, $minY, $maxX, $maxY];
$averageLatitude = $totalLatitude / $centroidCount;
$averageLongitude = $totalLongitude / $centroidCount;

$centroidOfCentroids = json_encode([
'type' => 'Point',
'coordinates' => [$averageLongitude, $averageLatitude],
]);

return $bboxCoordinates;
return $centroidOfCentroids;
}

public function updateProjectCentroid(string $projectUuid)
Expand All @@ -60,7 +74,10 @@ public function updateProjectCentroid(string $projectUuid)

Log::info("Centroid updated for projectUuid: $projectUuid");

return 'Centroids updated successfully!';
return response()->json([
'message' => 'Centroid updated',
'centroid' => $centroid,
], 200);
} catch (\Exception $e) {
Log::error("Error updating centroid for projectUuid: $projectUuid");

Expand All @@ -72,46 +89,29 @@ public function updateProjectCentroid(string $projectUuid)

}

public function centroidOfProject($projectUuid)
public static function getPolygonsBbox($polygonsIds)
{
$project = Project::where('uuid', $projectUuid)->first();

if (! $project) {
return null;
}

$polyIds = $project->sitePolygons()->pluck('poly_id')->toArray();

if (empty($polyIds)) {
return null;
}

$centroids = PolygonGeometry::selectRaw('ST_AsGeoJSON(ST_Centroid(geom)) AS centroid')
->whereIn('uuid', $polyIds)
$envelopes = PolygonGeometry::whereIn('uuid', $polygonsIds)
->selectRaw('ST_ASGEOJSON(ST_Envelope(geom)) as envelope')
->get();

if ($centroids->isEmpty()) {
return null; // Return null if no centroids are found
}
$maxX = $maxY = PHP_INT_MIN;
$minX = $minY = PHP_INT_MAX;

$centroidCount = $centroids->count();
$totalLatitude = 0;
$totalLongitude = 0;
foreach ($envelopes as $envelope) {
$geojson = json_decode($envelope->envelope);
$coordinates = $geojson->coordinates[0];

foreach ($centroids as $centroid) {
$centroidData = json_decode($centroid->centroid, true);
$totalLatitude += $centroidData['coordinates'][1];
$totalLongitude += $centroidData['coordinates'][0];
foreach ($coordinates as $point) {
$x = $point[0];
$y = $point[1];
$maxX = max($maxX, $x);
$minX = min($minX, $x);
$maxY = max($maxY, $y);
$minY = min($minY, $y);
}
}

$averageLatitude = $totalLatitude / $centroidCount;
$averageLongitude = $totalLongitude / $centroidCount;

$centroidOfCentroids = json_encode([
'type' => 'Point',
'coordinates' => [$averageLongitude, $averageLatitude],
]);

return $centroidOfCentroids;
return [$minX, $minY, $maxX, $maxY];
}
}
116 changes: 116 additions & 0 deletions app/Http/Controllers/V2/Dashboard/ActiveProjectsTableController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

namespace App\Http\Controllers\V2\Dashboard;

use App\Helpers\TerrafundDashboardQueryHelper;
use App\Http\Controllers\Controller;
use App\Models\V2\Forms\FormOptionList;
use App\Models\V2\Forms\FormOptionListOption;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;

class ActiveProjectsTableController extends Controller
{
public function __invoke(Request $request)
{
$perPage = $request->input('per_page', PHP_INT_MAX);
$page = $request->input('page', 1);

$projects = $this->getAllProjects($request, $perPage, $page);
$count = $this->getQuery($request)->count();

return response()->json([
'current_page' => $page,
'data' => $projects,
'per_page' => $perPage,
'last_page' => ceil($count / $perPage),
'total' => $count,
]);
}

public function getQuery($request)
{
return TerrafundDashboardQueryHelper::buildQueryFromRequest($request)
->with('organisation')
->withCount(['sites', 'nurseries']);
}

public function getAllProjects($request, $perPage, $page)
{
$query = $this->getQuery($request)
->skip(($page - 1) * $perPage)
->take($perPage);

$projects = $query->get();

return $projects->map(function ($project) {
return [
'uuid' => $project->uuid,
'name' => $project->name,
'organisation' => $project->organisation->name,
'trees_under_restoration' => $this->treesUnderRestoration($project),
'jobs_created' => $this->jobsCreated($project),
'volunteers' => $this->volunteers($project),
'beneficiaries' => $this->beneficiaries($project),
'survival_rate' => $project->survival_rate,
'number_of_sites' => $project->sites_count,
'number_of_nurseries' => $project->nurseries_count,
'project_country' => $this->projectCountry($project->country),
'country_slug' => $project->country,
'number_of_trees_goal' => $project->trees_grown_goal,
'date_added' => $project->created_at,
];
});
}

public function treesUnderRestoration($project)
{
return $project->trees_planted_count;
}

public function jobsCreated($project)
{
$projectReport = $project->reports()
->selectRaw('SUM(ft_total) as total_ft, SUM(pt_total) as total_pt')
->groupBy('project_id')
->first();

if ($projectReport) {
return $projectReport->total_ft + $projectReport->total_pt;
} else {
return 0;
}
}

public function volunteers($project)
{
$totalVolunteers = $project->reports()->selectRaw('SUM(volunteer_total) as total')->first();

return $totalVolunteers ? intval($totalVolunteers->total) : 0;
}

public function beneficiaries($project)
{
$totalBeneficiaries = $project->reports()->selectRaw('SUM(beneficiaries) as total')->first();

return $totalBeneficiaries ? intval($totalBeneficiaries->total) : 0;
}

public function projectCountry($slug)
{
$countryId = FormOptionList::where('key', 'countries')->value('id');

return FormOptionListOption::where('form_option_list_id', $countryId)
->where('slug', $slug)
->value('label');
}

public function paginate($items, $perPage = 10, $page = null, $options = [])
{
$page = $page ?: (LengthAwarePaginator::resolveCurrentPage() ?: 1);
$items = $items instanceof Collection ? $items : Collection::make($items);

return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
}
}
109 changes: 109 additions & 0 deletions app/Http/Controllers/V2/Dashboard/CountryDataController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

namespace App\Http\Controllers\V2\Dashboard;

use App\Http\Controllers\Controller;
use App\Models\V2\Projects\Project;
use App\Models\V2\Sites\SitePolygon;
use App\Models\V2\WorldCountryGeneralized;
use Illuminate\Support\Facades\Log;

class CountryDataController extends Controller
{
public function getCountryBbox(string $iso)
{
// Get the bbox of the country and the name
$countryData = WorldCountryGeneralized::where('iso', $iso)
->selectRaw('ST_AsGeoJSON(ST_Envelope(geometry)) AS bbox, country')
->first();

if (! $countryData) {
return response()->json(['error' => 'Country not found'], 404);
}

// Decode the GeoJSON bbox
$geoJson = json_decode($countryData->bbox);

// Extract the bounding box coordinates
$coordinates = $geoJson->coordinates[0];

// Get the country name
$countryName = $countryData->country;

// Construct the bbox data in the specified format
$countryBbox = [
$countryName,
[$coordinates[0][0], $coordinates[0][1], $coordinates[2][0], $coordinates[2][1]],
];

return response()->json(['bbox' => $countryBbox]);
}

public function getPolygonData(string $uuid)
{
$sitePolygon = SitePolygon::where('poly_id', $uuid)->first();

if (! $sitePolygon) {
return response()->json(['error' => 'Polygon not found'], 404);
}

$project = $sitePolygon->project()->first();

if (! $project) {
Log::error("Project not found for site polygon with ID: $sitePolygon->id");
}

$site = $sitePolygon->site()->first();

if(! $site) {
Log::error("Site not found for site polygon with ID: $sitePolygon->id");

}

$data = [
['key' => 'poly_name', 'title' => 'title', 'value' => $sitePolygon->poly_name ?? null],
['key' => 'project_name', 'title' => 'Project', 'value' => $project->name ?? null],
['key' => 'site_name', 'title' => 'Site', 'value' => $site?->name ?? null],
['key' => 'num_trees', 'title' => 'Number of trees', 'value' => $sitePolygon->num_trees ?? null],
['key' => 'plantstart', 'title' => 'Plant Start Date', 'value' => $sitePolygon->plantstart ?? null],
['key' => 'status', 'title' => 'Status', 'value' => $sitePolygon->status ?? null],

];

return response()->json(['data' => $data]);
}

public function getProjectData(string $uuid)
{
try {
$project = Project::isUuid($uuid)->first();

if (! $project) {
Log::error("Project not found for project with UUID: $uuid");

return response()->json(['error' => 'Project not found'], 404);
}
$countSitePolygons = $project->total_site_polygons;

$organization = $project->organisation()->first();
if (! $organization) {
Log::error("Organization not found for project with ID: $project->id");
}

$country = WorldCountryGeneralized::where('iso', $project->country)->first();
$data = [
['key' => 'project_name', 'title' => 'title', 'value' => $project->name],
['key' => 'country', 'title' => 'Country', 'value' => $country?->country],
['key' => 'polygon_counts', 'title' => 'No. of Site - Polygons', 'value' => $countSitePolygons],
['key' => 'organizations', 'title' => 'Organization', 'value' => $organization?->name],
];

return response()->json(['data' => $data]);
} catch (\Exception $e) {
Log::error($e->getMessage());

return response()->json(['error' => 'An error occurred while fetching project data', 'message' => $e->getMessage()], 500);
}

}
}
Loading

0 comments on commit 4846c75

Please sign in to comment.