Skip to content

Commit

Permalink
Merge pull request #201 from wri/release/gregarious-gopherwood
Browse files Browse the repository at this point in the history
[RELEASE] Gregarious Gopherwood
  • Loading branch information
roguenet authored May 17, 2024
2 parents bc1b3d2 + c16b9c3 commit 37739a7
Show file tree
Hide file tree
Showing 115 changed files with 5,613 additions and 934 deletions.
7 changes: 6 additions & 1 deletion app/Console/Commands/Migration/RolesMigrationCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function handle()

if (Role::where('name', 'admin-super')->count() === 0) {
$role = Role::create(['name' => 'admin-super']);
$role->givePermissionTo(['framework-terrafund', 'framework-ppc', 'framework-terrafund-enterprises', 'custom-forms-manage', 'users-manage', 'monitoring-manage', 'reports-manage']);
$role->givePermissionTo(['framework-terrafund', 'framework-ppc', 'framework-terrafund-enterprises', 'framework-hbf', 'custom-forms-manage', 'users-manage', 'monitoring-manage', 'reports-manage']);
}

if (Role::where('name', 'admin-ppc')->count() === 0) {
Expand All @@ -65,6 +65,11 @@ public function handle()
$role->givePermissionTo(['framework-terrafund', 'framework-terrafund-enterprises', 'custom-forms-manage', 'users-manage', 'monitoring-manage', 'reports-manage']);
}

if (Role::where('name', 'admin-hbf')->count() === 0) {
$role = Role::create(['name' => 'admin-hbf']);
$role->givePermissionTo(['framework-hbf', 'custom-forms-manage', 'users-manage', 'monitoring-manage', 'reports-manage']);
}

if (Role::where('name', 'project-developer')->count() === 0) {
$role = Role::create(['name' => 'project-developer']);
$role->givePermissionTo(['manage-own']);
Expand Down
138 changes: 138 additions & 0 deletions app/Console/Commands/OneOff/MigrateWorkdayData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?php

namespace App\Console\Commands\OneOff;

use App\Models\V2\Workdays\Workday;
use App\Models\V2\Workdays\WorkdayDemographic;
use Illuminate\Console\Command;
use Illuminate\Support\Str;

class MigrateWorkdayData extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'one-off:migrate-workday-data';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Updates Workday data to use the new workday_demographics table';

private const DEMOGRAPHICS = [
WorkdayDemographic::GENDER,
WorkdayDemographic::AGE,
WorkdayDemographic::ETHNICITY,
];

private const SUBTYPE_NULL = 'subtype-null';
private const NAME_NULL = 'name-null';

/**
* Execute the console command.
*/
public function handle()
{
$entityTypes = Workday::select('workdayable_type')->distinct()->pluck('workdayable_type');
foreach ($entityTypes as $entityType) {
$entityIds = Workday::where('workdayable_type', $entityType)
->select('workdayable_id')
->distinct()
->pluck('workdayable_id');
$count = $entityIds->count();
$shortName = explode_pop('\\', $entityType);
echo "Processing $shortName: $count records\n";

foreach ($entityIds as $entityId) {
$this->updateEntityWorkdays($entityType, $entityId);
}
}
}

private function updateEntityWorkdays(string $entityType, int $entityId): void
{
$workdayCollections = Workday::where(['workdayable_type' => $entityType, 'workdayable_id' => $entityId])
->get()
->reduce(function (array $carry, Workday $workday) {
$carry[$workday['collection']][] = $workday;

return $carry;
}, []);

foreach ($workdayCollections as $collection => $workdays) {
$mapping = $this->mapWorkdayCollection($workdays);
$framework_key = $workdays[0]->framework_key;

$workday = Workday::create([
'workdayable_type' => $entityType,
'workdayable_id' => $entityId,
'framework_key' => $framework_key,
'collection' => $collection,
]);
foreach ($mapping as $demographic => $subTypes) {
foreach ($subTypes as $subType => $names) {
foreach ($names as $name => $amount) {
WorkdayDemographic::create([
'workday_id' => $workday->id,
'type' => $demographic,
'subtype' => $subType == self::SUBTYPE_NULL ? null : $subType,
'name' => $name == self::NAME_NULL ? null : $name,
'amount' => $amount,
]);
}
}
}

$workdayIds = collect($workdays)->map(fn ($workday) => $workday->id)->all();
Workday::whereIn('id', $workdayIds)->update(['migrated_to_demographics' => true]);
Workday::whereIn('id', $workdayIds)->delete();
}
}

private function mapWorkdayCollection(array $workdays): array
{
$demographics = [];
foreach (self::DEMOGRAPHICS as $demographic) {
foreach ($workdays as $workday) {
$subType = $this->getSubtype($demographic, $workday);
$name = match ($workday[$demographic]) {
null, 'gender-undefined', 'age-undefined', 'decline-to-specify' => 'unknown',
default => $workday[$demographic],
};
if ($subType == 'unknown' && strcasecmp($name, 'unknown') == 0) {
// We only get an unknown subtype when we're working on ethnicity. If the value is also unknown in
// this case, we want to leave it null.
$name = self::NAME_NULL;
}

$current = data_get($demographics, "$demographic.$subType.$name");
data_set($demographics, "$demographic.$subType.$name", $current + $workday->amount);
}
}

return $demographics;
}

private function getSubtype(string $demographic, Workday $workday): string
{
if ($demographic != WorkdayDemographic::ETHNICITY) {
return self::SUBTYPE_NULL;
}

if ($workday->indigeneity != null && $workday->indigeneity != 'decline to specify') {
return $workday->indigeneity;
}

if (Str::startsWith($workday->ethnicity, 'indigenous')) {
return 'indigenous';
} elseif (Str::startsWith($workday->ethnicity, 'other')) {
return 'other';
}

return 'unknown';
}
}
41 changes: 41 additions & 0 deletions app/Console/Commands/OneOff/MigrateWorkdayOtherDescription.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace App\Console\Commands\OneOff;

use App\Models\V2\Projects\ProjectReport;
use App\Models\V2\Sites\SiteReport;
use Illuminate\Console\Command;

class MigrateWorkdayOtherDescription extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'one-off:migrate-workday-other-description';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Moves workday other description data from the reports to the workdays';

/**
* Execute the console command.
*/
public function handle()
{
foreach ([SiteReport::class, ProjectReport::class] as $reportClass) {
$query = $reportClass::whereNot('paid_other_activity_description', null);
echo "Updating $reportClass, instance count: " . (clone $query)->count() . "\n";

foreach ($query->get() as $report) {
$report->update(['other_workdays_description' => $report->paid_other_activity_description]);
}
}

echo "Migration complete!\n";
}
}
93 changes: 93 additions & 0 deletions app/Console/Commands/ReportWorkdayDiscrepancies.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace App\Console\Commands;

use App\Models\V2\Projects\ProjectReport;
use App\Models\V2\Sites\SiteReport;
use App\Models\V2\Workdays\Workday;
use Illuminate\Console\Command;

class ReportWorkdayDiscrepancies extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'report-workday-discrepancies';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Reports on project and site reports that have a difference between aggregated and disaggregated workday numbers';

private const PROPERTIES = [
ProjectReport::class => [
'paid' => [
Workday::COLLECTION_PROJECT_PAID_NURSERY_OPERATIONS,
Workday::COLLECTION_PROJECT_PAID_PROJECT_MANAGEMENT,
Workday::COLLECTION_PROJECT_PAID_OTHER,
],
'volunteer' => [
Workday::COLLECTION_PROJECT_VOLUNTEER_NURSERY_OPERATIONS,
Workday::COLLECTION_PROJECT_VOLUNTEER_PROJECT_MANAGEMENT,
Workday::COLLECTION_PROJECT_VOLUNTEER_OTHER,
],
],
SiteReport::class => [
'paid' => [
Workday::COLLECTION_SITE_PAID_SITE_ESTABLISHMENT,
Workday::COLLECTION_SITE_PAID_PLANTING,
Workday::COLLECTION_SITE_PAID_SITE_MAINTENANCE,
Workday::COLLECTION_SITE_PAID_SITE_MONITORING,
Workday::COLLECTION_SITE_PAID_OTHER,
],
'volunteer' => [
Workday::COLLECTION_SITE_VOLUNTEER_SITE_ESTABLISHMENT,
Workday::COLLECTION_SITE_VOLUNTEER_PLANTING,
Workday::COLLECTION_SITE_VOLUNTEER_SITE_MAINTENANCE,
Workday::COLLECTION_SITE_VOLUNTEER_SITE_MONITORING,
Workday::COLLECTION_SITE_VOLUNTEER_OTHER,
],
],
];

/**
* Execute the console command.
*/
public function handle()
{
echo "Model Type,Model UUID,Aggregate Paid Total,Disaggregate Paid Total,Aggregate Volunteer Total,Disaggregate Volunteer Total\n";
foreach (self::PROPERTIES as $model => $propertySets) {
$model::where('status', 'approved')->chunkById(
100,
function ($reports) use ($propertySets) {
foreach ($reports as $report) {
$aggregate_paid = (int)$report->workdays_paid;
$aggregate_volunteer = (int)$report->workdays_volunteer;

$modelType = get_class($report);
$query = Workday::where([
'workdayable_type' => $modelType,
'workdayable_id' => $report->id,
]);
if ($query->count() == 0) {
// Skip reports that have no associated workday rows.
continue;
}

$disaggregate_paid = (int)(clone $query)->whereIn('collection', $propertySets['paid'])->sum('amount');
$disaggregate_volunteer = (int)(clone $query)->whereIn('collection', $propertySets['volunteer'])->sum('amount');

if ($aggregate_paid != $disaggregate_paid || $aggregate_volunteer != $disaggregate_volunteer) {
$shortType = explode_pop('\\', $modelType);
echo "$shortType,$report->uuid,$aggregate_paid,$disaggregate_paid,$aggregate_volunteer,$disaggregate_volunteer\n";
}
}
}
);
}
}
}
26 changes: 20 additions & 6 deletions app/Exports/V2/BaseExportFormSubmission.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ protected function getAnswer(array $field, array $answers): string
if (is_array($answer)) {
$list = [];
foreach ($answer as $item) {
if (is_array($item)) {
$list[] = $item['amount'].':'.$item['gender'].':'.$item['age'].':'.$item['ethnicity'].':'.$item['indigeneity'];
} else {
$list[] = $item;
}
$list[] = data_get($field, 'input_type') . '??' . $item;
}

return implode('|', $list);
Expand All @@ -72,7 +68,25 @@ protected function getAnswer(array $field, array $answers): string
return $this->stringifyModel($answer, ['name', 'amount']);

case 'workdays':
return $this->stringifyModel($answer, ['amount', 'gender', 'age', 'ethnicity', 'indigeneity']);
$list = [];
$workday = $answer->first();
if ($workday == null) {
return '';
}

$types = ['gender' => [], 'age' => [], 'ethnicity' => []];
foreach ($workday->demographics as $demographic) {
$value = match ($demographic->type) {
'ethnicity' => [$demographic->amount, $demographic->subtype, $demographic->name],
default => [$demographic->amount, $demographic->name],
};
$types[$demographic['type']][] = implode(':', $value);
}
$list[] = 'gender:(' . implode(')(', $types['gender']) . ')';
$list[] = 'age:(' . implode(')(', $types['age']) . ')';
$list[] = 'ethnicity:(' . implode(')(', $types['ethnicity']) . ')';

return implode('|', $list);

case 'leadershipTeam':
return $this->stringifyModel($answer, ['first_name', 'last_name', 'position', 'gender', 'age',]);
Expand Down
6 changes: 3 additions & 3 deletions app/Exports/V2/EntityExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ protected function getAttachedMappedForEntity($entity): array
$organisation = $entity->organisation;

$mapped = [
$entity->old_id ?? ($entity->id ?? null),
$entity->ppc_external_id ?? $entity->old_id ?? $entity->id ?? null,
$entity->uuid,
$organisation->readable_type ?? null,
$organisation->name ?? null,
Expand All @@ -77,7 +77,7 @@ protected function getAttachedMappedForEntity($entity): array
];

if (in_array($this->form->type, ['nursery', 'nursery-report','site', 'site-report', 'project-report'])) {
$mapped[] = $entity->project->old_id ?? ($entity->project->id ?? null);
$mapped[] = $entity->project->ppc_external_id ?? $entity->project->id ?? null;
}

if ($this->form->type === 'project-report') {
Expand All @@ -92,7 +92,7 @@ protected function getAttachedMappedForEntity($entity): array
}

if ($this->form->type === 'site-report') {
$mapped[] = $entity->site->old_id ?? ($entity->site->id ?? null);
$mapped[] = $entity->site->ppc_external_id ?? $entity->site->id ?? null;
$mapped[] = $entity->site->name ?? null;
$sumTreeSPecies = $entity->treeSpecies()->sum('amount');
$mapped[] = $sumTreeSPecies > 0 ? $sumTreeSPecies : null;
Expand Down
Loading

0 comments on commit 37739a7

Please sign in to comment.