Skip to content

Commit

Permalink
Merge pull request #99 from wri/release/careening-croton
Browse files Browse the repository at this point in the history
[RELEASE] Careening Croton
  • Loading branch information
roguenet authored Mar 21, 2024
2 parents 9ffb190 + 77858ee commit ebab764
Show file tree
Hide file tree
Showing 18 changed files with 224 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function __invoke(Request $request, Project $project)
$form = $this->getForm(Project::class, $project->framework_key);
$this->authorize('export', [Project::class, $form, $project]);

$filename = public_path('storage/'.Str::of($project->name)->replace(['/', '\\'], '-') . ' full export - ' . now() . '.zip');
$filename = storage_path('./'.Str::of($project->name)->replace(['/', '\\'], '-') . ' full export - ' . now() . '.zip');
$zip = new \ZipArchive();
$zip->open($filename, \ZipArchive::CREATE);

Expand All @@ -39,6 +39,9 @@ public function __invoke(Request $request, Project $project)
rescue(function () use ($project, $zip) {
$this->addSiteReportsExports($project, $zip);
});
rescue(function () use ($project, $zip) {
$this->addSiteShapefiles($project, $zip);
});
rescue(function () use ($project, $zip) {
$this->addNurseriesExports($project, $zip);
});
Expand Down Expand Up @@ -66,6 +69,16 @@ private function addSiteReportsExports(Project $project, \ZipArchive $mainZip):
}
}

private function addSiteShapefiles(Project $project, \ZipArchive $mainZip): void
{
$shapefilesFolder = 'Sites Shapefiles/';
$mainZip->addEmptyDir($shapefilesFolder);

foreach ($project->sites as $site) {
$filename = $shapefilesFolder . Str::of($site->name)->replace(['/', '\\'], '-') . '.geojson';
$mainZip->addFromString($filename, $site->boundary_geojson);
}
}
private function addNurseryReportsExports(Project $project, \ZipArchive $mainZip): void
{
$form = $this->getForm(NurseryReport::class, $project->framework_key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ public function __invoke(Request $request, Project $project, string $entity)
{
ini_set('memory_limit', '-1');
Validator::make(['entity' => $entity], [
'entity' => 'required|in:sites,nurseries,project-reports',
'entity' => 'required|in:sites,nurseries,project-reports,shapefiles',
])->validate();

if ($entity === 'shapefiles') {
return $this->exportShapefiles($project);
}

$modelClass = $this->getModelClass($entity);

$form = $this->getForm($modelClass, $project->framework_key);
Expand Down Expand Up @@ -63,4 +67,31 @@ private function getModelClass(string $entity)

return $model;
}

private function exportShapefiles(Project $project)
{
$filename = storage_path('./'.Str::of($project->name)->replace(['/', '\\'], '-') . ' Sites Shapefiles - ' . now() . '.zip');
$zip = new \ZipArchive();
$zip->open($filename, \ZipArchive::CREATE);

rescue(function () use ($project, $zip) {
$this->addSiteShapefiles($project, $zip);
});

$zip->close();

return response()->download($filename)->deleteFileAfterSend();
}

private function addSiteShapefiles(Project $project, \ZipArchive $mainZip): void
{
$shapefilesFolder = 'Sites Shapefiles/';
$mainZip->addEmptyDir($shapefilesFolder);

foreach ($project->sites as $site) {
$geojsonFilename = $shapefilesFolder . Str::of($site->name)->replace(['/', '\\'], '-') . '.geojson';
$mainZip->addFromString($geojsonFilename, $site->boundary_geojson);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function __invoke(Request $request, Nursery $nursery): NurseryReportsColl
AllowedFilter::exact('framework_key'),
])
->where('nursery_id', $nursery->id)
->isComplete();
->hasBeenSubmitted();

if (in_array($request->query('sort'), $sortableColumns)) {
$qry->allowedSorts($sortableColumns);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function __invoke(Request $request, Project $project): ProjectReportsColl
AllowedFilter::exact('update_request_status'),
])
->where('project_id', $project->id)
->isComplete();
->hasBeenSubmitted();

if (in_array($request->query('sort'), $sortableColumns)) {
$qry->allowedSorts($sortableColumns);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ public function __invoke(Request $request, Project $project): TasksCollection

$sortableColumns = [
'status', '-status',
'period_key', '-period_key',
'due_at', '-due_at',
];

$query = Task::with(['project'])
->isIncomplete()
->where('project_id', $project->id);
$query = QueryBuilder::for(Task::class)
->with('project')
->where('project_id', $project->id)
->defaultSort('-due_at');

if (in_array($request->query('sort'), $sortableColumns)) {
$query->allowedSorts($sortableColumns);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function __invoke(Request $request, Site $site): SiteReportsCollection
AllowedFilter::exact('framework_key'),
])
->where('site_id', $site->id)
->isComplete();
->hasBeenSubmitted();

if (in_array($request->query('sort'), $sortableColumns)) {
$qry->allowedSorts($sortableColumns);
Expand Down
1 change: 0 additions & 1 deletion app/Http/Resources/V2/Projects/ProjectLiteResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ public function toArray($request)
'organisation' => new OrganisationLiteResource($this->organisation),
'planting_start_date' => $this->planting_start_date,
'has_monitoring_data' => $this->has_monitoring_data,
'total_reporting_tasks' => $this->total_reporting_tasks,
'project_reports_total' => $this->project_reports_total,
];

Expand Down
2 changes: 2 additions & 0 deletions app/Http/Resources/V2/Sites/SiteResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public function toArray($request)
'updated_at' => $this->updated_at,
'has_monitoring_data' => empty($this->has_monitoring_data) ? false : true,
'seeds_planted_count' => $this->seeds_planted_count,
'siting_strategy' => $this->siting_strategy,
'description_siting_strategy' => $this->description_siting_strategy,
];

return $this->appendFilesToResource($data);
Expand Down
2 changes: 2 additions & 0 deletions app/Jobs/GenerateApplicationExportJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public function __construct(FundingProgramme $fundingProgramme)

public function handle()
{
ini_set('memory_limit', '-1');

$name = 'exports/' . $this->fundingProgramme->name . ' Export - ' . now() . '.csv';

$export = (new ApplicationExport($this->fundingProgramme->applications()->getQuery(), $this->fundingProgramme));
Expand Down
10 changes: 10 additions & 0 deletions app/Models/Traits/HasReportStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public function supportsNothingToReport(): bool
ReportStatusStateMachine::APPROVED => 'Approved',
];

public const UNSUBMITTED_STATUSES = [
ReportStatusStateMachine::DUE,
ReportStatusStateMachine::STARTED,
];

public const COMPLETE_STATUSES = [
ReportStatusStateMachine::AWAITING_APPROVAL,
ReportStatusStateMachine::APPROVED,
Expand All @@ -60,6 +65,11 @@ public function scopeIsComplete(Builder $query): Builder
return $query->whereIn('status', self::COMPLETE_STATUSES);
}

public function scopeHasBeenSubmitted(Builder $query): Builder
{
return $query->whereNotIn('status', self::UNSUBMITTED_STATUSES);
}

public function isEditable(): bool
{
return in_array($this->status, [ReportStatusStateMachine::DUE, ReportStatusStateMachine::STARTED]) ||
Expand Down
76 changes: 38 additions & 38 deletions app/Models/V2/Projects/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use App\Models\V2\Sites\SiteReport;
use App\Models\V2\Tasks\Task;
use App\Models\V2\TreeSpecies\TreeSpecies;
use App\StateMachines\EntityStatusStateMachine;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
Expand All @@ -31,6 +32,7 @@
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Laravel\Scout\Searchable;
use OwenIt\Auditing\Auditable;
use OwenIt\Auditing\Contracts\Auditable as AuditableContract;
Expand Down Expand Up @@ -305,29 +307,16 @@ public function getProjectReportsTotalAttribute(): int

public function getTreesPlantedCountAttribute(): int
{
$siteIds = Site::where('project_id', $this->id)
->isApproved()
->pluck('id')
->toArray();

$submissionsIds = SiteReport::whereIn('site_id', $siteIds)
->isComplete()
->pluck('id')
->toArray();

return TreeSpecies::where('speciesable_type', SiteReport::class)
->whereIn('speciesable_id', $submissionsIds)
->whereIn('speciesable_id', $this->submittedSiteReportIds())
->where('collection', TreeSpecies::COLLECTION_PLANTED)
->sum('amount');
}

public function getSeedsPlantedCountAttribute(): int
{
$siteIds = $this->sites()->pluck('id')->toArray();
$submissionsIds = SiteReport::whereIn('site_id', $siteIds)->pluck('id')->toArray();

return Seeding::where('seedable_type', SiteReport::class)
->whereIn('seedable_id', $submissionsIds)
->whereIn('seedable_id', $this->submittedSiteReportIds())
->sum('amount');
}

Expand All @@ -344,22 +333,15 @@ public function getRegeneratedTreesCountAttribute(): int

public function getWorkdayCountAttribute(): int
{
$paid = $this->reports()->isApproved()->sum('workdays_paid');
$volunteer = $this->reports()->isApproved()->sum('workdays_volunteer');

$siteIds = $this->sites()->pluck('id')->toArray();

$sitePaid = SiteReport::whereIn('id', $siteIds)
->where('due_at', '<', now())
->isComplete()
->sum('workdays_paid');

$siteVolunteer = SiteReport::whereIn('id', $siteIds)
->where('due_at', '<', now())
->isComplete()
->sum('workdays_volunteer');

return $paid + $volunteer + $sitePaid + $siteVolunteer;
$sumQueries = [
DB::raw("sum(`workdays_paid`) as paid"),
DB::raw("sum(`workdays_volunteer`) as volunteer"),
];
$projectTotals = $this->reports()->hasBeenSubmitted()->get($sumQueries)->first();
// The groupBy is superfluous, but required because Laravel adds "v2_sites.project_id as laravel_through_key" to
// the SQL select.
$siteTotals = $this->submittedSiteReports()->groupBy('v2_sites.project_id')->get($sumQueries)->first();
return $projectTotals?->paid + $projectTotals?->volunteer + $siteTotals?->paid + $siteTotals?->volunteer;
}

public function getTotalJobsCreatedAttribute(): int
Expand Down Expand Up @@ -398,12 +380,12 @@ public function getTotalOverdueReportsAttribute(): int
->isIncomplete()
->count();

$sOverdue = SiteReport::whereIn('id', $siteIds)
$sOverdue = SiteReport::whereIn('site_id', $siteIds)
->where('due_at', '<', now())
->isIncomplete()
->count();

$nOverdue = NurseryReport::whereIn('id', $nurseryIds)
$nOverdue = NurseryReport::whereIn('nursery_id', $nurseryIds)
->where('due_at', '<', now())
->isIncomplete()
->count();
Expand All @@ -416,11 +398,6 @@ public function getHasMonitoringDataAttribute(): int
return $this->monitoring()->count() > 0 ? 1 : 0;
}

public function getTotalReportingTasksAttribute(): int
{
return $this->tasks()->isIncomplete()->count();
}

public function getFrameworkUuidAttribute(): ?string
{
return $this->framework ? $this->framework->uuid : null;
Expand All @@ -447,4 +424,27 @@ public function toSearchableArray()
'name' => $this->name,
];
}

/**
* @return HasManyThrough A relation for all site reports associated with this project that is for an approved
* site, and has a report status past due/started (has been submitted).
*/
private function submittedSiteReports(): HasManyThrough
{
return $this
->siteReports()
->where('v2_sites.status', EntityStatusStateMachine::APPROVED)
->whereNotIn('v2_site_reports.status', SiteReport::UNSUBMITTED_STATUSES);
}

/**
* @return array The array of site report IDs for all reports associated with sites that have been approved, and
* have a report status not in due or started (reports that have been submitted).
*/
private function submittedSiteReportIds(): array
{
// scopes that use status don't work on the HasManyThrough because both Site and SiteReport have
// a status field.
return $this->submittedSiteReports()->pluck('v2_site_reports.id')->toArray();
}
}
4 changes: 2 additions & 2 deletions app/Models/V2/Projects/ProjectReport.php
Original file line number Diff line number Diff line change
Expand Up @@ -387,14 +387,14 @@ public function getWorkdaysTotalAttribute(): int

$sitePaid = SiteReport::whereIn('id', $siteIds)
->where('due_at', '<', now())
->isComplete()
->hasBeenSubmitted()
->whereMonth('due_at', $month)
->whereYear('due_at', $year)
->sum('workdays_paid');

$siteVolunteer = SiteReport::whereIn('id', $siteIds)
->where('due_at', '<', now())
->isComplete()
->hasBeenSubmitted()
->whereMonth('due_at', $month)
->whereYear('due_at', $year)
->sum('workdays_volunteer');
Expand Down
11 changes: 8 additions & 3 deletions app/Models/V2/Sites/Site.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Laravel\Scout\Searchable;
use OwenIt\Auditing\Auditable;
use OwenIt\Auditing\Contracts\Auditable as AuditableContract;
Expand Down Expand Up @@ -82,6 +83,8 @@ class Site extends Model implements HasMedia, AuditableContract, EntityModel
'aim_number_of_mature_trees',
'land_use_types',
'restoration_strategy',
'siting_strategy',
'description_siting_strategy',
'framework_key',
'old_id',
'old_model',
Expand Down Expand Up @@ -289,10 +292,12 @@ public function getRegeneratedTreesCountAttribute(): int

public function getWorkdayCountAttribute(): int
{
$volunteers = $this->reports()->sum('workdays_volunteer');
$paid = $this->reports()->sum('workdays_paid');
$totals = $this->reports()->hasBeenSubmitted()->get([
DB::raw("sum(`workdays_volunteer`) as volunteer"),
DB::raw("sum(`workdays_paid`) as paid"),
])->first();

return $volunteers + $paid;
return $totals?->paid + $totals?->volunteer;
}

public function getFrameworkUuidAttribute(): ?string
Expand Down
2 changes: 2 additions & 0 deletions config/wri/linked-fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,8 @@
'site-aim-number-of-mature-trees' => ['property' => 'aim_number_of_mature_trees', 'label' => 'Aim number of mature trees', 'input_type' => 'number'],
'site-start-date' => ['property' => 'start_date', 'label' => 'Start date', 'input_type' => 'date'],
'site-end-date' => ['property' => 'end_date', 'label' => 'End date', 'input_type' => 'date'],
'site-description-siting-strategy' => ['property' => 'description_siting_strategy', 'label' => 'Description siting strategy', 'input_type' => 'text'],
'site-col-siting-strategy' => ['property' => 'siting_strategy', 'label' => 'Siting Strategy', 'input_type' => 'select', 'multichoice' => false, 'option_list_key' => 'siting-strategy-collection'],
],
'file-collections' => [
'site-col-media' => ['property' => 'media', 'label' => 'Media', 'input_type' => 'file', 'multichoice' => true],
Expand Down
Loading

0 comments on commit ebab764

Please sign in to comment.