diff --git a/app/Enums/Area.php b/app/Enums/Area.php new file mode 100644 index 0000000..86dc046 --- /dev/null +++ b/app/Enums/Area.php @@ -0,0 +1,26 @@ + __('app.area.urban'), + self::RURAL => __('app.area.rural'), + }; + } +} diff --git a/app/Exceptions/InvalidSourceUrlException.php b/app/Exceptions/InvalidSourceUrlException.php index 0b3707c..f1c1ca4 100644 --- a/app/Exceptions/InvalidSourceUrlException.php +++ b/app/Exceptions/InvalidSourceUrlException.php @@ -8,5 +8,8 @@ class InvalidSourceUrlException extends Exception { -// + public function __construct(string $url) + { + parent::__construct("Invalid source url: {$url}"); + } } diff --git a/app/Exceptions/MissingSourceFileException.php b/app/Exceptions/MissingSourceFileException.php new file mode 100644 index 0000000..4d6a9c8 --- /dev/null +++ b/app/Exceptions/MissingSourceFileException.php @@ -0,0 +1,15 @@ +schema([ Forms\Components\Section::make() + ->maxWidth(MaxWidth::ThreeExtraLarge) + ->columns(2) ->schema([ Select::make('type') ->label(__('admin.field.type')) @@ -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'), ]; } } diff --git a/app/Jobs/Europarl240609/Turnout/FetchTurnoutDataJob.php b/app/Jobs/Europarl240609/Turnout/FetchTurnoutDataJob.php index 9ef42a7..7be33eb 100644 --- a/app/Jobs/Europarl240609/Turnout/FetchTurnoutDataJob.php +++ b/app/Jobs/Europarl240609/Turnout/FetchTurnoutDataJob.php @@ -13,8 +13,6 @@ class FetchTurnoutDataJob extends SchedulableJob { - public int $chunk = 500; - public static function name(): string { return 'Europarlamentare 09.06.2024 / Prezență'; @@ -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() @@ -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(); } /** diff --git a/app/Jobs/Europarl240609/Turnout/ImportCountyStatisticsJob.php b/app/Jobs/Europarl240609/Turnout/ImportCountyStatisticsJob.php new file mode 100644 index 0000000..e771911 --- /dev/null +++ b/app/Jobs/Europarl240609/Turnout/ImportCountyStatisticsJob.php @@ -0,0 +1,108 @@ +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 + */ + public function tags(): array + { + return [ + 'import', + 'statistics', + 'scheduled_job:' . $this->scheduledJob->id, + 'election:' . $this->scheduledJob->election_id, + 'county:' . $this->county->code, + ]; + } +} diff --git a/app/Jobs/Europarl240609/Turnout/ImportCountyTurnoutJob.php b/app/Jobs/Europarl240609/Turnout/ImportCountyTurnoutJob.php index 4de3f3c..d58f5fd 100644 --- a/app/Jobs/Europarl240609/Turnout/ImportCountyTurnoutJob.php +++ b/app/Jobs/Europarl240609/Turnout/ImportCountyTurnoutJob.php @@ -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; @@ -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(); @@ -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. * diff --git a/app/Models/ScheduledJob.php b/app/Models/ScheduledJob.php index 1d39a14..e6f63d1 100644 --- a/app/Models/ScheduledJob.php +++ b/app/Models/ScheduledJob.php @@ -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 { @@ -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, [ @@ -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; diff --git a/app/Models/Statistic.php b/app/Models/Statistic.php new file mode 100644 index 0000000..63176b5 --- /dev/null +++ b/app/Models/Statistic.php @@ -0,0 +1,58 @@ +crossJoin([ + '18-24', '25-34', '35-44', '45-64', '65+', + // ...range(18, 120), + ]); + } + + protected function casts(): array + { + return [ + 'area' => Area::class, + ...static::segments() + ->mapWithKeys(fn (array $segment) => [ + "{$segment[0]}_{$segment[1]}" => 'integer', + ]) + ->all(), + ]; + } + + public function election(): BelongsTo + { + return $this->belongsTo(Election::class); + } + + public function country(): BelongsTo + { + return $this->belongsTo(Country::class); + } + + public function county(): BelongsTo + { + return $this->belongsTo(County::class); + } + + public function locality(): BelongsTo + { + return $this->belongsTo(Locality::class); + } +} diff --git a/bootstrap/app.php b/bootstrap/app.php index 87f71c6..f857cf1 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -2,9 +2,13 @@ declare(strict_types=1); +use Filament\Facades\Filament; +use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; +use Illuminate\Queue\Console\PruneBatchesCommand; +use Laravel\Horizon\Console\SnapshotCommand; use Sentry\Laravel\Integration; return Application::configure(basePath: dirname(__DIR__)) @@ -15,9 +19,24 @@ health: '/up', ) ->withMiddleware(function (Middleware $middleware) { - // + // Fix for `Route [login] not defined` exception + // @see https://github.com/filamentphp/filament/discussions/5226#discussioncomment-10555366 + $middleware->redirectGuestsTo(fn () => Filament::getCurrentPanel()?->getLoginUrl() ?? route('front.index')); }) ->withExceptions(function (Exceptions $exceptions) { Integration::handles($exceptions); }) + ->withSchedule(function (Schedule $schedule) { + $schedule + ->command(SnapshotCommand::class) + ->everyFiveMinutes(); + + $schedule + ->command(PruneBatchesCommand::class, [ + 'hours' => 24 * 7, + 'unfinished' => 24 * 7, + 'cancelled' => 24 * 7, + ]) + ->daily(); + }) ->create(); diff --git a/config/horizon.php b/config/horizon.php index 51fd188..7786c36 100644 --- a/config/horizon.php +++ b/config/horizon.php @@ -190,6 +190,19 @@ 'timeout' => 60, 'nice' => 0, ], + 'supervisor-2' => [ + 'connection' => 'redis', + 'queue' => ['sequential'], + 'balance' => 'false', + 'autoScalingStrategy' => 'time', + 'maxProcesses' => 1, + 'maxTime' => 0, + 'maxJobs' => 0, + 'memory' => 128, + 'tries' => 1, + 'timeout' => 60, + 'nice' => 0, + ], ], 'environments' => [ diff --git a/database/migrations/0001_01_10_000000_create_turnouts_table.php b/database/migrations/0001_01_10_000000_create_turnouts_table.php index 68b5cfa..fa63c72 100644 --- a/database/migrations/0001_01_10_000000_create_turnouts_table.php +++ b/database/migrations/0001_01_10_000000_create_turnouts_table.php @@ -74,7 +74,7 @@ public function up(): void // $table->unique(['election_id', 'locality_id']); $table->unique(['election_id', 'county_id', 'section']); - // $table->unique(['election_id', 'country_id']); + $table->unique(['election_id', 'country_id', 'section']); // $table->integer('eligible_voters')->unsigned(); // $table->mediumInteger('total_votes')->unsigned(); diff --git a/database/migrations/0001_01_10_000001_create_statistics_table.php b/database/migrations/0001_01_10_000001_create_statistics_table.php new file mode 100644 index 0000000..15a729e --- /dev/null +++ b/database/migrations/0001_01_10_000001_create_statistics_table.php @@ -0,0 +1,272 @@ +id(); + + $table->foreignIdFor(Election::class) + ->constrained() + ->cascadeOnDelete(); + + $table->foreignIdFor(Country::class) + ->nullable() + ->constrained() + ->cascadeOnDelete(); + + $table->smallInteger('county_id') + ->unsigned() + ->nullable(); + + $table->foreign('county_id') + ->references('id') + ->on('counties'); + + $table->mediumInteger('locality_id') + ->unsigned() + ->nullable(); + + $table->foreign('locality_id') + ->references('id') + ->on('localities'); + + $table->string('section'); + + $table->string('area', 1)->nullable(); + + $table->unique(['election_id', 'county_id', 'section']); + $table->unique(['election_id', 'country_id', 'section']); + + $table->mediumInteger('men_18-24')->unsigned(); + $table->mediumInteger('men_25-34')->unsigned(); + $table->mediumInteger('men_35-44')->unsigned(); + $table->mediumInteger('men_45-64')->unsigned(); + $table->mediumInteger('men_65+')->unsigned(); + $table->mediumInteger('women_18-24')->unsigned(); + $table->mediumInteger('women_25-34')->unsigned(); + $table->mediumInteger('women_35-44')->unsigned(); + $table->mediumInteger('women_45-64')->unsigned(); + $table->mediumInteger('women_65+')->unsigned(); + + // $table->mediumInteger('men_18')->unsigned(); + // $table->mediumInteger('men_19')->unsigned(); + // $table->mediumInteger('men_20')->unsigned(); + // $table->mediumInteger('men_21')->unsigned(); + // $table->mediumInteger('men_22')->unsigned(); + // $table->mediumInteger('men_23')->unsigned(); + // $table->mediumInteger('men_24')->unsigned(); + // $table->mediumInteger('men_25')->unsigned(); + // $table->mediumInteger('men_26')->unsigned(); + // $table->mediumInteger('men_27')->unsigned(); + // $table->mediumInteger('men_28')->unsigned(); + // $table->mediumInteger('men_29')->unsigned(); + // $table->mediumInteger('men_30')->unsigned(); + // $table->mediumInteger('men_31')->unsigned(); + // $table->mediumInteger('men_32')->unsigned(); + // $table->mediumInteger('men_33')->unsigned(); + // $table->mediumInteger('men_34')->unsigned(); + // $table->mediumInteger('men_35')->unsigned(); + // $table->mediumInteger('men_36')->unsigned(); + // $table->mediumInteger('men_37')->unsigned(); + // $table->mediumInteger('men_38')->unsigned(); + // $table->mediumInteger('men_39')->unsigned(); + // $table->mediumInteger('men_40')->unsigned(); + // $table->mediumInteger('men_41')->unsigned(); + // $table->mediumInteger('men_42')->unsigned(); + // $table->mediumInteger('men_43')->unsigned(); + // $table->mediumInteger('men_44')->unsigned(); + // $table->mediumInteger('men_45')->unsigned(); + // $table->mediumInteger('men_46')->unsigned(); + // $table->mediumInteger('men_47')->unsigned(); + // $table->mediumInteger('men_48')->unsigned(); + // $table->mediumInteger('men_49')->unsigned(); + // $table->mediumInteger('men_50')->unsigned(); + // $table->mediumInteger('men_51')->unsigned(); + // $table->mediumInteger('men_52')->unsigned(); + // $table->mediumInteger('men_53')->unsigned(); + // $table->mediumInteger('men_54')->unsigned(); + // $table->mediumInteger('men_55')->unsigned(); + // $table->mediumInteger('men_56')->unsigned(); + // $table->mediumInteger('men_57')->unsigned(); + // $table->mediumInteger('men_58')->unsigned(); + // $table->mediumInteger('men_59')->unsigned(); + // $table->mediumInteger('men_60')->unsigned(); + // $table->mediumInteger('men_61')->unsigned(); + // $table->mediumInteger('men_62')->unsigned(); + // $table->mediumInteger('men_63')->unsigned(); + // $table->mediumInteger('men_64')->unsigned(); + // $table->mediumInteger('men_65')->unsigned(); + // $table->mediumInteger('men_66')->unsigned(); + // $table->mediumInteger('men_67')->unsigned(); + // $table->mediumInteger('men_68')->unsigned(); + // $table->mediumInteger('men_69')->unsigned(); + // $table->mediumInteger('men_70')->unsigned(); + // $table->mediumInteger('men_71')->unsigned(); + // $table->mediumInteger('men_72')->unsigned(); + // $table->mediumInteger('men_73')->unsigned(); + // $table->mediumInteger('men_74')->unsigned(); + // $table->mediumInteger('men_75')->unsigned(); + // $table->mediumInteger('men_76')->unsigned(); + // $table->mediumInteger('men_77')->unsigned(); + // $table->mediumInteger('men_78')->unsigned(); + // $table->mediumInteger('men_79')->unsigned(); + // $table->mediumInteger('men_80')->unsigned(); + // $table->mediumInteger('men_81')->unsigned(); + // $table->mediumInteger('men_82')->unsigned(); + // $table->mediumInteger('men_83')->unsigned(); + // $table->mediumInteger('men_84')->unsigned(); + // $table->mediumInteger('men_85')->unsigned(); + // $table->mediumInteger('men_86')->unsigned(); + // $table->mediumInteger('men_87')->unsigned(); + // $table->mediumInteger('men_88')->unsigned(); + // $table->mediumInteger('men_89')->unsigned(); + // $table->mediumInteger('men_90')->unsigned(); + // $table->mediumInteger('men_91')->unsigned(); + // $table->mediumInteger('men_92')->unsigned(); + // $table->mediumInteger('men_93')->unsigned(); + // $table->mediumInteger('men_94')->unsigned(); + // $table->mediumInteger('men_95')->unsigned(); + // $table->mediumInteger('men_96')->unsigned(); + // $table->mediumInteger('men_97')->unsigned(); + // $table->mediumInteger('men_98')->unsigned(); + // $table->mediumInteger('men_99')->unsigned(); + // $table->mediumInteger('men_100')->unsigned(); + // $table->mediumInteger('men_101')->unsigned(); + // $table->mediumInteger('men_102')->unsigned(); + // $table->mediumInteger('men_103')->unsigned(); + // $table->mediumInteger('men_104')->unsigned(); + // $table->mediumInteger('men_105')->unsigned(); + // $table->mediumInteger('men_106')->unsigned(); + // $table->mediumInteger('men_107')->unsigned(); + // $table->mediumInteger('men_108')->unsigned(); + // $table->mediumInteger('men_109')->unsigned(); + // $table->mediumInteger('men_110')->unsigned(); + // $table->mediumInteger('men_111')->unsigned(); + // $table->mediumInteger('men_112')->unsigned(); + // $table->mediumInteger('men_113')->unsigned(); + // $table->mediumInteger('men_114')->unsigned(); + // $table->mediumInteger('men_115')->unsigned(); + // $table->mediumInteger('men_116')->unsigned(); + // $table->mediumInteger('men_117')->unsigned(); + // $table->mediumInteger('men_118')->unsigned(); + // $table->mediumInteger('men_119')->unsigned(); + // $table->mediumInteger('men_120')->unsigned(); + // $table->mediumInteger('women_18')->unsigned(); + // $table->mediumInteger('women_19')->unsigned(); + // $table->mediumInteger('women_20')->unsigned(); + // $table->mediumInteger('women_21')->unsigned(); + // $table->mediumInteger('women_22')->unsigned(); + // $table->mediumInteger('women_23')->unsigned(); + // $table->mediumInteger('women_24')->unsigned(); + // $table->mediumInteger('women_25')->unsigned(); + // $table->mediumInteger('women_26')->unsigned(); + // $table->mediumInteger('women_27')->unsigned(); + // $table->mediumInteger('women_28')->unsigned(); + // $table->mediumInteger('women_29')->unsigned(); + // $table->mediumInteger('women_30')->unsigned(); + // $table->mediumInteger('women_31')->unsigned(); + // $table->mediumInteger('women_32')->unsigned(); + // $table->mediumInteger('women_33')->unsigned(); + // $table->mediumInteger('women_34')->unsigned(); + // $table->mediumInteger('women_35')->unsigned(); + // $table->mediumInteger('women_36')->unsigned(); + // $table->mediumInteger('women_37')->unsigned(); + // $table->mediumInteger('women_38')->unsigned(); + // $table->mediumInteger('women_39')->unsigned(); + // $table->mediumInteger('women_40')->unsigned(); + // $table->mediumInteger('women_41')->unsigned(); + // $table->mediumInteger('women_42')->unsigned(); + // $table->mediumInteger('women_43')->unsigned(); + // $table->mediumInteger('women_44')->unsigned(); + // $table->mediumInteger('women_45')->unsigned(); + // $table->mediumInteger('women_46')->unsigned(); + // $table->mediumInteger('women_47')->unsigned(); + // $table->mediumInteger('women_48')->unsigned(); + // $table->mediumInteger('women_49')->unsigned(); + // $table->mediumInteger('women_50')->unsigned(); + // $table->mediumInteger('women_51')->unsigned(); + // $table->mediumInteger('women_52')->unsigned(); + // $table->mediumInteger('women_53')->unsigned(); + // $table->mediumInteger('women_54')->unsigned(); + // $table->mediumInteger('women_55')->unsigned(); + // $table->mediumInteger('women_56')->unsigned(); + // $table->mediumInteger('women_57')->unsigned(); + // $table->mediumInteger('women_58')->unsigned(); + // $table->mediumInteger('women_59')->unsigned(); + // $table->mediumInteger('women_60')->unsigned(); + // $table->mediumInteger('women_61')->unsigned(); + // $table->mediumInteger('women_62')->unsigned(); + // $table->mediumInteger('women_63')->unsigned(); + // $table->mediumInteger('women_64')->unsigned(); + // $table->mediumInteger('women_65')->unsigned(); + // $table->mediumInteger('women_66')->unsigned(); + // $table->mediumInteger('women_67')->unsigned(); + // $table->mediumInteger('women_68')->unsigned(); + // $table->mediumInteger('women_69')->unsigned(); + // $table->mediumInteger('women_70')->unsigned(); + // $table->mediumInteger('women_71')->unsigned(); + // $table->mediumInteger('women_72')->unsigned(); + // $table->mediumInteger('women_73')->unsigned(); + // $table->mediumInteger('women_74')->unsigned(); + // $table->mediumInteger('women_75')->unsigned(); + // $table->mediumInteger('women_76')->unsigned(); + // $table->mediumInteger('women_77')->unsigned(); + // $table->mediumInteger('women_78')->unsigned(); + // $table->mediumInteger('women_79')->unsigned(); + // $table->mediumInteger('women_80')->unsigned(); + // $table->mediumInteger('women_81')->unsigned(); + // $table->mediumInteger('women_82')->unsigned(); + // $table->mediumInteger('women_83')->unsigned(); + // $table->mediumInteger('women_84')->unsigned(); + // $table->mediumInteger('women_85')->unsigned(); + // $table->mediumInteger('women_86')->unsigned(); + // $table->mediumInteger('women_87')->unsigned(); + // $table->mediumInteger('women_88')->unsigned(); + // $table->mediumInteger('women_89')->unsigned(); + // $table->mediumInteger('women_90')->unsigned(); + // $table->mediumInteger('women_91')->unsigned(); + // $table->mediumInteger('women_92')->unsigned(); + // $table->mediumInteger('women_93')->unsigned(); + // $table->mediumInteger('women_94')->unsigned(); + // $table->mediumInteger('women_95')->unsigned(); + // $table->mediumInteger('women_96')->unsigned(); + // $table->mediumInteger('women_97')->unsigned(); + // $table->mediumInteger('women_98')->unsigned(); + // $table->mediumInteger('women_99')->unsigned(); + // $table->mediumInteger('women_100')->unsigned(); + // $table->mediumInteger('women_101')->unsigned(); + // $table->mediumInteger('women_102')->unsigned(); + // $table->mediumInteger('women_103')->unsigned(); + // $table->mediumInteger('women_104')->unsigned(); + // $table->mediumInteger('women_105')->unsigned(); + // $table->mediumInteger('women_106')->unsigned(); + // $table->mediumInteger('women_107')->unsigned(); + // $table->mediumInteger('women_108')->unsigned(); + // $table->mediumInteger('women_109')->unsigned(); + // $table->mediumInteger('women_110')->unsigned(); + // $table->mediumInteger('women_111')->unsigned(); + // $table->mediumInteger('women_112')->unsigned(); + // $table->mediumInteger('women_113')->unsigned(); + // $table->mediumInteger('women_114')->unsigned(); + // $table->mediumInteger('women_115')->unsigned(); + // $table->mediumInteger('women_116')->unsigned(); + // $table->mediumInteger('women_117')->unsigned(); + // $table->mediumInteger('women_118')->unsigned(); + // $table->mediumInteger('women_119')->unsigned(); + // $table->mediumInteger('women_120')->unsigned(); + }); + } +}; diff --git a/lang/ro/app.php b/lang/ro/app.php index ba1dd86..c3b4310 100644 --- a/lang/ro/app.php +++ b/lang/ro/app.php @@ -68,4 +68,9 @@ 'every_10_8_minutes' => '10+8 minute', 'every_10_9_minutes' => '10+9 minute', ], + + 'area' => [ + 'urban' => 'Urban', + 'rural' => 'Rural', + ], ]; diff --git a/routes/web.php b/routes/web.php index 7bceeaf..a3bf9da 100644 --- a/routes/web.php +++ b/routes/web.php @@ -4,6 +4,6 @@ use Illuminate\Support\Facades\Route; -Route::get('/', function () { - return view('welcome'); +Route::as('front.')->group(function () { + Route::view('/', 'welcome')->name('index'); });