Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
andreiio committed Oct 25, 2024
1 parent 51d43df commit 985b7f8
Show file tree
Hide file tree
Showing 16 changed files with 564 additions and 42 deletions.
26 changes: 26 additions & 0 deletions app/Enums/Area.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\Enums;

use App\Concerns\Enums\Arrayable;
use App\Concerns\Enums\Comparable;
use Filament\Support\Contracts\HasLabel;

enum Area: string implements HasLabel
{
use Arrayable;
use Comparable;

case URBAN = 'U';
case RURAL = 'R';

public function getLabel(): ?string
{
return match ($this) {
self::URBAN => __('app.area.urban'),
self::RURAL => __('app.area.rural'),
};
}
}
5 changes: 4 additions & 1 deletion app/Exceptions/InvalidSourceUrlException.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@

class InvalidSourceUrlException extends Exception
{
//
public function __construct(string $url)
{
parent::__construct("Invalid source url: {$url}");
}
}
15 changes: 15 additions & 0 deletions app/Exceptions/MissingSourceFileException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace App\Exceptions;

use Exception;

class MissingSourceFileException extends Exception
{
public function __construct(string $path)
{
parent::__construct("Missing source file: {$path}");
}
}
5 changes: 4 additions & 1 deletion app/Exceptions/MissingSourceUrlException.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@

class MissingSourceUrlException extends Exception
{
//
public function __construct()
{
parent::__construct('Missing source url');
}
}
23 changes: 8 additions & 15 deletions app/Filament/Admin/Resources/ElectionResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Filament\Admin\Resources;

use App\Filament\Admin\Resources\ElectionResource\Pages;
use App\Filament\Admin\Resources\ElectionResource\RelationManagers\ScheduledJobRelationManager;
use App\Models\Election;
use Filament\Forms;
use Filament\Forms\Components\Select;
Expand All @@ -16,9 +17,8 @@
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Infolist;
use Filament\Pages\SubNavigationPosition;
use Filament\Resources\Pages\EditRecord;
use Filament\Resources\Pages\Page;
use Filament\Resources\Resource;
use Filament\Support\Enums\MaxWidth;
use Filament\Tables;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
Expand Down Expand Up @@ -58,6 +58,8 @@ public static function form(Form $form): Form
return $form
->schema([
Forms\Components\Section::make()
->maxWidth(MaxWidth::ThreeExtraLarge)
->columns(2)
->schema([
Select::make('type')
->label(__('admin.field.type'))
Expand Down Expand Up @@ -172,27 +174,18 @@ public static function table(Table $table): Table
->defaultSort('id', 'desc');
}

public static function getRecordSubNavigation(Page $page): array
public static function getRelations(): array
{
return [];
if ($page instanceof EditRecord) {
return [];
}

return $page->generateNavigationItems([
Pages\ViewElection::class,
Pages\EditElection::class,
// Pages\ElectionRounds\ManageElectionRounds::class,
]);
return [
ScheduledJobRelationManager::class,
];
}

public static function getPages(): array
{
return [
'index' => Pages\ListElections::route('/'),
'create' => Pages\CreateElection::route('/create'),
'view' => Pages\ViewElection::route('/{record}'),
'edit' => Pages\EditElection::route('/{record}/edit'),
];
}
}
28 changes: 17 additions & 11 deletions app/Jobs/Europarl240609/Turnout/FetchTurnoutDataJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

class FetchTurnoutDataJob extends SchedulableJob
{
public int $chunk = 500;

public static function name(): string
{
return 'Europarlamentare 09.06.2024 / Prezență';
Expand Down Expand Up @@ -45,11 +43,6 @@ public function execute(): void

$tmpDisk->delete('turnout.csv');

logger()->info('DispatchTurnoutJob', [
'path' => $cwd,
'files' => $tmpDisk->allFiles(),
]);

collect($tmpDisk->allFiles())
->each(function (string $file) use ($tmpDisk) {
$this->scheduledJob->disk()
Expand All @@ -59,10 +52,23 @@ public function execute(): void
);
});

Bus::batch(
County::all()
->map(fn (County $county) => new ImportCountyTurnoutJob($this->scheduledJob, $county))
)->dispatch();
$counties = County::all();

$electionName = $this->scheduledJob->election->getFilamentName();

$time = now()->toDateTimeString();

Bus::chain([
Bus::batch(
$counties
->map(fn (County $county) => new ImportCountyTurnoutJob($this->scheduledJob, $county))
)->name("$electionName / Prezență / $time"),

Bus::batch(
$counties
->map(fn (County $county) => new ImportCountyStatisticsJob($this->scheduledJob, $county))
)->name("$electionName / Statistici / $time"),
])->onQueue('sequential')->dispatch();
}

/**
Expand Down
108 changes: 108 additions & 0 deletions app/Jobs/Europarl240609/Turnout/ImportCountyStatisticsJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

declare(strict_types=1);

namespace App\Jobs\Europarl240609\Turnout;

use App\Exceptions\MissingSourceFileException;
use App\Models\County;
use App\Models\ScheduledJob;
use App\Models\Statistic;
use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\SkipIfBatchCancelled;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
use League\Csv\Reader;

class ImportCountyStatisticsJob implements ShouldQueue
{
use Batchable;
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;

public ScheduledJob $scheduledJob;

public County $county;

public function __construct(ScheduledJob $scheduledJob, County $county)
{
$this->scheduledJob = $scheduledJob;
$this->county = $county;
}

public function handle(): void
{
$disk = $this->scheduledJob->disk();
$path = $this->scheduledJob->getSourcePath("{$this->county->code}.csv");

if (! $disk->exists($path)) {
throw new MissingSourceFileException($path);
}

$reader = Reader::createFromStream($disk->readStream($path));
$reader->setHeaderOffset(0);

logger()->info('ImportCountyStatisticsJob', [
'county' => $this->county->code,
'first' => $reader->count(),
]);

$values = collect();

$records = $reader->getRecords();
foreach ($records as $record) {
$values->push([
'election_id' => $this->scheduledJob->election_id,
'county_id' => $this->county->id,
'locality_id' => $record['Siruta'],
'area' => $record['Mediu'],
'section' => $record['Nr sectie de votare'],
...Statistic::segments()
->mapWithKeys(function (array $segment) use ($record) {
$gender = match ($segment[0]) {
'men' => 'Barbati',
'women' => 'Femei',
};

return [
"{$segment[0]}_{$segment[1]}" => data_get($record, "{$gender} {$segment[1]}", 0),
];
})
->all(),
]);
}

$values->chunk(200)
->each(fn (Collection $chunk) => Statistic::upsert(
$chunk->all(),
['election_id', 'county_id', 'section'],
));
}

public function middleware(): array
{
return [new SkipIfBatchCancelled];
}

/**
* Get the tags that should be assigned to the job.
*
* @return array<int, string>
*/
public function tags(): array
{
return [
'import',
'statistics',
'scheduled_job:' . $this->scheduledJob->id,
'election:' . $this->scheduledJob->election_id,
'county:' . $this->county->code,
];
}
}
15 changes: 8 additions & 7 deletions app/Jobs/Europarl240609/Turnout/ImportCountyTurnoutJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@

namespace App\Jobs\Europarl240609\Turnout;

use App\Exceptions\MissingSourceFileException;
use App\Models\County;
use App\Models\ScheduledJob;
use App\Models\Turnout;
use Exception;
use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\SkipIfBatchCancelled;
use Illuminate\Queue\SerializesModels;
use League\Csv\Reader;

Expand Down Expand Up @@ -40,17 +41,12 @@ public function handle(): void
$path = $this->scheduledJob->getSourcePath("{$this->county->code}.csv");

if (! $disk->exists($path)) {
throw new Exception('Missing source file for county ' . $this->county->code);
throw new MissingSourceFileException($path);
}

$reader = Reader::createFromStream($disk->readStream($path));
$reader->setHeaderOffset(0);

logger()->info('ImportCountyTurnoutJob', [
'county' => $this->county->code,
'first' => $reader->count(),
]);

$values = collect();

$records = $reader->getRecords();
Expand All @@ -77,6 +73,11 @@ public function handle(): void
);
}

public function middleware(): array
{
return [new SkipIfBatchCancelled];
}

/**
* Get the tags that should be assigned to the job.
*
Expand Down
6 changes: 3 additions & 3 deletions app/Models/ScheduledJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Storage;

class ScheduledJob extends Model
{
Expand Down Expand Up @@ -87,7 +87,7 @@ public function requiresAuthentication(): bool
public function getPreparedSourceUrl(array $map = []): string
{
if (blank($this->source_url)) {
throw new MissingSourceUrlException();
throw new MissingSourceUrlException;
}

$map = array_merge($map, [
Expand All @@ -103,7 +103,7 @@ public function getPreparedSourceUrl(array $map = []): string
);

if (filter_var($url, \FILTER_VALIDATE_URL) === false) {
throw new InvalidSourceUrlException();
throw new InvalidSourceUrlException($url);
}

return $url;
Expand Down
Loading

0 comments on commit 985b7f8

Please sign in to comment.