Skip to content

Commit

Permalink
Merge pull request #207 from wri/feat/TM-931-other-description-export
Browse files Browse the repository at this point in the history
[TM-931] Handle the new location of other description and workdays data structure in exports
  • Loading branch information
roguenet authored May 17, 2024
2 parents 4408415 + b797f7e commit c16b9c3
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 71 deletions.
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";
}
}
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
2 changes: 1 addition & 1 deletion app/Exports/V2/EntityExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
30 changes: 19 additions & 11 deletions app/Helpers/CustomFormHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class CustomFormHelper
* @param string $framework [ppc,terrafund]
* @return Form
*/
public static function generateFakeForm(string $type, string $framework): Form
public static function generateFakeForm(string $type, string $framework, bool $withRelations = false): Form
{
switch ($type) {
case 'project':
Expand Down Expand Up @@ -59,16 +59,24 @@ public static function generateFakeForm(string $type, string $framework): Form

$form = Form::factory()->create(['framework_key' => $framework, 'model' => $model]);
$section = FormSection::factory()->create(['form_id' => $form->uuid]);
foreach (config('wri.linked-fields.models.' . $type . '.fields') as $key => $fieldCfg) {
FormQuestion::factory()->create(
[
'input_type' => data_get($fieldCfg, 'input_type'),
'label' => data_get($fieldCfg, 'label'),
'name' => data_get($fieldCfg, 'label'),
'form_section_id' => $section->id,
'linked_field_key' => $key,
]
);

$generateQuestions = function ($subtype) use ($type, $section) {
foreach (config("wri.linked-fields.models.$type.$subtype") as $key => $fieldCfg) {
FormQuestion::factory()->create(
[
'input_type' => data_get($fieldCfg, 'input_type'),
'label' => data_get($fieldCfg, 'label'),
'name' => data_get($fieldCfg, 'label'),
'form_section_id' => $section->id,
'linked_field_key' => $key,
]
);
}
};

$generateQuestions('fields');
if ($withRelations) {
$generateQuestions('relations');
}

$conditional = FormQuestion::factory()->conditionalField()->create(['form_section_id' => $section->id]);
Expand Down
53 changes: 38 additions & 15 deletions app/Models/Traits/HasWorkdays.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,50 @@
namespace App\Models\Traits;

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

/**
* @property int workdays_paid
* @property int workdays_volunteer
* @property string other_workdays_description
*/
trait HasWorkdays
{
public static function bootHasWorkdays()
{
foreach (array_keys(static::WORKDAY_COLLECTIONS) as $collection) {
self::resolveRelationUsing(
'workdays' . Str::studly($collection),
function ($entity) use ($collection) {
return $entity->workdays()->collection($collection);
}
);
}
collect([static::WORKDAY_COLLECTIONS['paid'], static::WORKDAY_COLLECTIONS['volunteer']])
->flatten()
->each(function ($collection) {
self::resolveRelationUsing(
'workdays' . Str::studly($collection),
function ($entity) use ($collection) {
return $entity->workdays()->collection($collection);
}
);
});
}

public function workdays()
{
return $this->morphMany(Workday::class, 'workdayable');
}

public function getWorkdaysPaidAttribute(): int
{
return $this->sumTotalWorkdaysAmounts(self::WORKDAY_COLLECTIONS['paid']);
}

public function getWorkdaysVolunteerAttribute(): int
{
return $this->sumTotalWorkdaysAmounts(self::WORKDAY_COLLECTIONS['volunteer']);
}

public function getOtherWorkdaysDescriptionAttribute(): ?string
{
return $this
->workdays()
->whereIn('collection', self::OTHER_WORKDAY_COLLECTIONS)
->collections(self::WORKDAY_COLLECTIONS['other'])
->orderBy('updated_at', 'desc')
->select('description')
->first()
Expand All @@ -37,10 +55,9 @@ public function getOtherWorkdaysDescriptionAttribute(): ?string

public function setOtherWorkdaysDescriptionAttribute(?string $value): void
{
$workdaysQuery = $this->morphMany(Workday::class, 'workdayable');
if (! empty($value)) {
foreach (self::OTHER_WORKDAY_COLLECTIONS as $collection) {
if (! (clone $workdaysQuery)->where('collection', $collection)->exists()) {
foreach (self::WORKDAY_COLLECTIONS['other'] as $collection) {
if (! $this->workdays()->collection($collection)->exists()) {
Workday::create([
'workdayable_type' => get_class($this),
'workdayable_id' => $this->id,
Expand All @@ -49,8 +66,14 @@ public function setOtherWorkdaysDescriptionAttribute(?string $value): void
}
}
}
$workdaysQuery
->whereIn('collection', self::OTHER_WORKDAY_COLLECTIONS)
->update(['description' => $value]);

$this->workdays()->collections(self::WORKDAY_COLLECTIONS['other'])->update(['description' => $value]);
}

protected function sumTotalWorkdaysAmounts(array $collections): int
{
// Assume that the types are balanced, and just return the value from `gender`
return WorkdayDemographic::whereIn('workday_id', $this->workdays()->collections($collections)->select('id'))
->gender()->sum('amount');
}
}
58 changes: 29 additions & 29 deletions app/Models/V2/Projects/ProjectReport.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use App\Models\V2\TreeSpecies\TreeSpecies;
use App\Models\V2\User;
use App\Models\V2\Workdays\Workday;
use App\Models\V2\Workdays\WorkdayDemographic;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
Expand Down Expand Up @@ -79,8 +80,6 @@ class ProjectReport extends Model implements MediaModel, AuditableContract, Repo
'completion',
'planted_trees',
'title',
'workdays_paid',
'workdays_volunteer',
'technical_narrative',
'public_narrative',
'landscape_community_contribution',
Expand Down Expand Up @@ -179,10 +178,21 @@ class ProjectReport extends Model implements MediaModel, AuditableContract, Repo
];

// Required by the HasWorkdays trait
public const WORKDAY_COLLECTIONS = Workday::PROJECT_COLLECTION;
public const OTHER_WORKDAY_COLLECTIONS = [
Workday::COLLECTION_PROJECT_PAID_OTHER,
Workday::COLLECTION_PROJECT_VOLUNTEER_OTHER,
public const WORKDAY_COLLECTIONS = [
'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,
],
'other' => [
Workday::COLLECTION_PROJECT_PAID_OTHER,
Workday::COLLECTION_PROJECT_VOLUNTEER_OTHER,
],
];

public function registerMediaConversions(Media $media = null): void
Expand Down Expand Up @@ -345,32 +355,22 @@ public function getTotalJobsCreatedAttribute(): int

public function getWorkdaysTotalAttribute(): int
{
$paid = $this->workdays_paid ?? 0;
$volunteer = $this->workdays_volunteer ?? 0;

if (empty($this->due_at)) {
return $paid + $volunteer;
} else {
$siteIds = $this->project->sites()->pluck('project_id')->toArray();
$month = $this->due_at->month;
$year = $this->due_at->year;
$projectReportTotal = $this->workdays_paid + $this->workdays_volunteer;

$sitePaid = SiteReport::whereIn('id', $siteIds)
->where('due_at', '<', now())
->hasBeenSubmitted()
->whereMonth('due_at', $month)
->whereYear('due_at', $year)
->sum('workdays_paid');
if (empty($this->task_id)) {
return $projectReportTotal;
}

$siteVolunteer = SiteReport::whereIn('id', $siteIds)
->where('due_at', '<', now())
->hasBeenSubmitted()
->whereMonth('due_at', $month)
->whereYear('due_at', $year)
->sum('workdays_volunteer');
// Assume that the types are balanced and just return the value from 'gender'
$sumTotals = fn ($collectionType) => WorkdayDemographic::whereIn(
'workday_id',
Workday::where('workdayable_type', SiteReport::class)
->whereIn('workdayable_id', $this->task->siteReports()->hasBeenSubmitted()->select('id'))
->collections(SiteReport::WORKDAY_COLLECTIONS[$collectionType])
->select('id')
)->gender()->sum('amount');

return $paid + $volunteer + $sitePaid + $siteVolunteer;
}
return $projectReportTotal + $sumTotals('paid') + $sumTotals('volunteer');
}

public function getSiteReportsCountAttribute(): int
Expand Down
25 changes: 19 additions & 6 deletions app/Models/V2/Sites/SiteReport.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ class SiteReport extends Model implements MediaModel, AuditableContract, ReportM
'approved_by',
'created_by',
'submitted_at',
'workdays_paid',
'workdays_volunteer',
'technical_narrative',
'public_narrative',
'disturbance_details',
Expand Down Expand Up @@ -145,10 +143,25 @@ class SiteReport extends Model implements MediaModel, AuditableContract, ReportM
];

// Required by the HasWorkdays trait
public const WORKDAY_COLLECTIONS = Workday::SITE_COLLECTIONS;
public const OTHER_WORKDAY_COLLECTIONS = [
Workday::COLLECTION_SITE_PAID_OTHER,
Workday::COLLECTION_SITE_VOLUNTEER_OTHER,
public const WORKDAY_COLLECTIONS = [
'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,
],
'other' => [
Workday::COLLECTION_SITE_PAID_OTHER,
Workday::COLLECTION_SITE_VOLUNTEER_OTHER,
],
];

public function registerMediaConversions(Media $media = null): void
Expand Down
5 changes: 5 additions & 0 deletions app/Models/V2/Workdays/Workday.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ public function scopeCollection(Builder $query, string $collection): Builder
return $query->where('collection', $collection);
}

public function scopeCollections(Builder $query, array $collections): Builder
{
return $query->whereIn('collection', $collections);
}

public function demographics(): HasMany
{
return $this->hasMany(WorkdayDemographic::class);
Expand Down
Loading

0 comments on commit c16b9c3

Please sign in to comment.