Skip to content

Commit

Permalink
Merge branch 'main' into feat/api
Browse files Browse the repository at this point in the history
  • Loading branch information
andreiio authored Nov 13, 2024
2 parents 4d726e2 + dde0ac3 commit 33d98b4
Show file tree
Hide file tree
Showing 86 changed files with 2,415 additions and 929 deletions.
46 changes: 46 additions & 0 deletions app/Actions/CheckRecordHasIssues.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace App\Actions;

class CheckRecordHasIssues
{
public function checkTurnout(array $record): bool
{
$computedTotal = collect(['LP', 'LC', 'LS', 'UM'])
->map(fn (string $key) => $record[$key])
->sum();

if ($computedTotal !== $record['LT']) {
return true;
}

return false;
}

public function checkRecord(array $record): bool
{
if ($record['a'] != $record['a1'] + $record['a2']) {
return true;
}

if ($record['a1'] < $record['b1']) {
return true;
}

if ($record['a2'] < $record['b2']) {
return true;
}

if ($record['b'] != $record['b1'] + $record['b2'] + $record['b3']) {
return true;
}

if ($record['c'] < $record['d'] + $record['e'] + $record['f']) {
return true;
}

return false;
}
}
25 changes: 25 additions & 0 deletions app/Actions/CheckVotable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace App\Actions;

use Illuminate\Support\Str;

class CheckVotable
{
private function getIndependentCandidatePrefix(): string
{
return config('import.independent_candidate_prefix');
}

public function isIndependentCandidate(string $name): bool
{
return Str::startsWith($name, $this->getIndependentCandidatePrefix());
}

public function getName(string $name): string
{
return Str::afterLast($name, $this->getIndependentCandidatePrefix());
}
}
60 changes: 60 additions & 0 deletions app/Actions/GenerateMappedVotablesList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace App\Actions;

use App\Enums\Time;
use App\Models\Candidate;
use App\Models\Party;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;

class GenerateMappedVotablesList
{
public function votables(array $header): Collection
{
return Cache::remember(
hash('xxh128', implode(',', $header)),
Time::MINUTE_IN_SECONDS,
fn () => collect($header)
->filter(fn (string $column) => $this->hasVotesSuffix($column))
->mapWithKeys(fn (string $column) => [
$column => $this->getCandidateOrParty($column),
])
);
}

protected function getVotesSuffix(): string
{
return config('import.candidate_votes_suffix');
}

protected function hasVotesSuffix(string $column): bool
{
return Str::endsWith($column, $this->getVotesSuffix());
}

protected function getCandidateOrParty(string $name): array
{
$name = Str::before($name, $this->getVotesSuffix());

$votable = Party::query()
->where('name', $name)
->firstOr(
fn () => Candidate::query()
->where('name', $name)
->first()
);

if (blank($votable)) {
throw new \Exception("Votable not found for column: {$name}");
}

return [
'votable_type' => $votable?->getMorphClass(),
'votable_id' => $votable?->id,
];
}
}
11 changes: 7 additions & 4 deletions app/Concerns/BelongsToElection.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@ public function initializeBelongsToElection(): void
protected static function bootBelongsToElection(): void
{
static::creating(function (self $model) {
if (! Filament::auth()->check()) {
// No need to change the election id if it's already set.
if (filled($model->election_id)) {
return;
}

if (! Filament::hasTenancy()) {
if (! Filament::auth()->check() || ! Filament::hasTenancy()) {
return;
}

$model->election()->associate(Filament::getTenant());
// There's no tenant outside of Filament.
if (filled($election = Filament::getTenant())) {
$model->election()->associate($election);
}
});

static::addGlobalScope(new BelongsToElectionScope);
Expand Down
83 changes: 83 additions & 0 deletions app/Concerns/CanGroupByDataLevel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

declare(strict_types=1);

namespace App\Concerns;

use App\Enums\DataLevel;
use Illuminate\Database\Eloquent\Builder;
use Tpetry\QueryExpressions\Language\Alias;
use Tpetry\QueryExpressions\Value\Value;

trait CanGroupByDataLevel
{
public function scopeForDataLevel(Builder $query, DataLevel $level, ?string $country = null, ?int $county = null, ?int $locality = null, bool $aggregate = false): Builder
{
if ($level->is(DataLevel::TOTAL)) {
$query->groupByTotal();
}

if ($level->is(DataLevel::DIASPORA)) {
$query->whereNotNull('country_id');

if (filled($country)) {
$query->where('country_id', $country);
}

if (! $aggregate) {
$query->groupByCountry();
}
}

if ($level->is(DataLevel::NATIONAL)) {
$query->whereNull('country_id');

if (filled($locality)) {
$query->where('locality_id', $locality)
->groupByLocality();
} elseif (filled($county)) {
$query->where('county_id', $county);

if ($aggregate) {
$query->groupByCounty();
} else {
$query->groupByLocality();
}
} else {
$query->whereNotNull('locality_id')
->whereNotNull('county_id');

if ($aggregate) {
$query->groupByTotal();
} else {
$query->groupByCounty();
}
}
}

return $query;
}

public function scopeGroupByCountry(Builder $query): Builder
{
return $query->groupBy('country_id')
->addSelect(new Alias('country_id', 'place'));
}

public function scopeGroupByCounty(Builder $query): Builder
{
return $query->groupBy('county_id')
->addSelect(new Alias('county_id', 'place'));
}

public function scopeGroupByLocality(Builder $query): Builder
{
return $query->groupBy('locality_id')
->addSelect(new Alias('locality_id', 'place'));
}

public function scopeGroupByTotal(Builder $query): Builder
{
return $query->addSelect(new Alias(new Value(1), 'place'));
}
}
35 changes: 0 additions & 35 deletions app/Concerns/CanGroupByPlace.php

This file was deleted.

10 changes: 10 additions & 0 deletions app/Contracts/HasDisplayName.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace App\Contracts;

interface HasDisplayName
{
public function getDisplayName(): string;
}
28 changes: 28 additions & 0 deletions app/Enums/Part.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace App\Enums;

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

enum Part: int implements HasLabel
{
use Arrayable;
use Comparable;

case PROV = 0;
case PART = 1;
case FINAL = 2;

public function getLabel(): ?string
{
return match ($this) {
self::PROV => __('app.part.prov'),
self::PART => __('app.part.part'),
self::FINAL => __('app.part.final'),
};
}
}
15 changes: 15 additions & 0 deletions app/Enums/Time.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace App\Enums;

enum Time: int
{
case MINUTE_IN_SECONDS = 60;
case HOUR_IN_SECONDS = 60 * 60;
case DAY_IN_SECONDS = 60 * 60 * 24;
case WEEK_IN_SECONDS = 60 * 60 * 24 * 7;
case MONTH_IN_SECONDS = 60 * 60 * 24 * 7 * 30;
case YEAR_IN_SECONDS = 60 * 60 * 24 * 7 * 30 * 365;
}
12 changes: 12 additions & 0 deletions app/Events/CountryCodeNotFound.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,16 @@ public function __construct(string $country, Election $election)
$this->country = $country;
$this->election = $election;
}

// /**
// * Get the channels the event should broadcast on.
// *
// * @return array<int, \Illuminate\Broadcasting\Channel>
// */
// public function broadcastOn(): array
// {
// return [
// new PrivateChannel('channel-name'),
// ];
// }
}
Loading

0 comments on commit 33d98b4

Please sign in to comment.