-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #201 from wri/release/gregarious-gopherwood
[RELEASE] Gregarious Gopherwood
- Loading branch information
Showing
115 changed files
with
5,613 additions
and
934 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
41
app/Console/Commands/OneOff/MigrateWorkdayOtherDescription.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"; | ||
} | ||
} | ||
} | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.