diff --git a/app/Filament/Imports/PointImporter.php b/app/Filament/Imports/PointImporter.php new file mode 100644 index 00000000..7627832d --- /dev/null +++ b/app/Filament/Imports/PointImporter.php @@ -0,0 +1,239 @@ +label(__('map_points.fields.latitude')) + ->example('27.9506') + ->requiredMapping(), + + ImportColumn::make('longitude') + ->label(__('map_points.fields.longitude')) + ->example('27.9506') + ->requiredMapping(), + + ImportColumn::make('pointType') + ->label(__('map_points.fields.point_type')) + ->example('Punct de colectare') + ->requiredMapping() + ->relationship('pointType', 'name') + ->rules( + [ + 'required', + 'string', + ] + ), + + ImportColumn::make('county') + ->requiredMapping() + ->example('București') + ->label(__('map_points.county')) + ->relationship(name:'county', resolveUsing: 'name') + ->rules( + [ + 'required', + 'string', + ] + ), + + ImportColumn::make('city_id') + ->label(__('map_points.city')) + ->example('Sector 2') + ->fillRecordUsing( + function (Point $record, string $state) { + $cityId = City::search($state)->where('county', $record->county->name)->first()?->id ?? 0; + if ($cityId !== 0) { + $record->city_id = $cityId; + } + } + ) + ->requiredMapping() + ->rules( + [ + 'required', + 'string', + ] + ), + + ImportColumn::make('address') + ->label(__('map_points.fields.address')) + ->example('Strada Ștefan cel Mare 1') + ->ignoreBlankState(), + + ImportColumn::make('notes') + ->label(__('map_points.fields.notes')) + ->ignoreBlankState(), + + ImportColumn::make('observations') + ->label(__('map_points.fields.observations')) + ->ignoreBlankState(), + + ImportColumn::make('administered_by') + ->label(__('map_points.fields.administered_by')) + ->ignoreBlankState(), + + ImportColumn::make('business_name') + ->label(__('map_points.fields.business_name')) + ->ignoreBlankState(), + + ImportColumn::make('offers_money') + ->label(__('map_points.fields.offers_money')) + ->ignoreBlankState(), + + ImportColumn::make('offers_transport') + ->label(__('map_points.fields.offers_transport')) + ->ignoreBlankState(), + + ImportColumn::make('schedule') + ->label(__('map_points.fields.schedule')) + ->ignoreBlankState(), + + ImportColumn::make('email') + ->label(__('map_points.fields.email')) + ->ignoreBlankState(), + + ImportColumn::make('website') + ->label(__('map_points.fields.website')) + ->ignoreBlankState(), + + ImportColumn::make('materials') + ->label(__('map_points.fields.materials')) + ->array(',') + ->ignoreBlankState(), + + ]; + } + + public function resolveRecord(): ?Point + { + $this->data['location'] = new PointObject((float) $this->data['latitude'], (float) $this->data['longitude']); + unset($this->data['latitude'], $this->data['longitude']); + + return new Point(); + } + + public static function getCompletedNotificationBody(Import $import): string + { + $body = 'Your point import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.'; + + if ($failedRowsCount = $import->getFailedRowsCount()) { + $body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.'; + } + + return $body; + } + + public static function getOptionsFormComponents(): array + { + return [ + Select::make('service_type_id') + ->label(__('map_points.fields.service_type')) + ->live() + ->options( + ServiceType::all()->pluck('name', 'id')->toArray() + )->required(), + + Toggle::make('import_materials') + ->label(__('map_points.import_materials')) + ->hidden(fn (Get $get) => ! ServiceType::find($get('service_type_id'))?->can_collect_materials) + ->default(false), + + Section::make(__('map_points.use_default_values'))->columns(2)->schema( + [ + TextInput::make('default_administered_by') + ->label(__('map_points.fields.administered_by')), + TextInput::make('default_business_name') + ->label(__('map_points.fields.business_name')), + + Toggle::make('default_offers_money') + ->label(__('map_points.fields.offers_money')), + Toggle::make('default_offers_transport') + ->label(__('map_points.fields.offers_transport')), + + TextInput::make('default_schedule') + ->label(__('map_points.fields.schedule')), + + Select::make('point_group_id') + ->label(__('map_points.fields.group')) + ->options( + PointGroup::all()->pluck('name', 'id')->toArray() + ), + + ] + ), + + ]; + } + + public function saveRecord(): void + { + $materials = $this->data['materials'] ?? []; + unset($this->data['materials']); + unset($this->record->materials); + + $this->setMetadata(); + + $this->checkDefaultFields(); + + parent::saveRecord(); // TODO: Change the autogenerated stub + if ($this->options['import_materials']) { + collect($materials)->each(function ($material) { + $this->record->materials()->attach(Material::search($material)->first()); + }); + } + } + + private function checkDefaultFields(): void + { + if (blank($this->record->administered_by)) { + $this->record->administered_by = $this->options['default_administered_by']; + } + if (blank($this->record->business_name)) { + $this->record->business_name = $this->options['default_business_name']; + } + if (blank($this->record->offers_money)) { + $this->record->offers_money = $this->options['default_offers_money']; + } + if (blank($this->record->offers_transport)) { + $this->record->offers_transport = $this->options['default_offers_transport']; + } + if (blank($this->record->schedule)) { + $this->record->schedule = $this->options['default_schedule']; + } + } + + private function setMetadata(): void + { + $this->record->location = $this->data['location']; + $this->record->service_type_id = $this->options['service_type_id']; + $this->record->created_by = auth()->id(); + $this->record->source = Source::IMPORT; + $this->record->status = Status::VERIFIED; + } +} diff --git a/app/Filament/Resources/ImportResource.php b/app/Filament/Resources/ImportResource.php deleted file mode 100644 index a6acf052..00000000 --- a/app/Filament/Resources/ImportResource.php +++ /dev/null @@ -1,164 +0,0 @@ -schema([ - // - ]); - } - - public static function table(Table $table): Table - { - return $table - ->columns([ - TextColumn::make('file') - ->label(__('import.columns.file')) - ->sortable() - ->searchable(), - TextColumn::make('createdBy.fullname') - ->label(__('import.columns.user')) - ->sortable() - ->searchable(), - TextColumn::make('created_at') - ->label(__('import.columns.created_at')) - ->sortable() - ->searchable(), - TextColumn::make('started_at') - ->label(__('import.columns.started_at')) - ->sortable() - ->searchable(), - TextColumn::make('finished_at') - ->label(__('import.columns.finished_at')) - ->sortable() - ->searchable(), - TextColumn::make('processed') - ->label(__('import.columns.processed')) - ->sortable() - ->searchable() - ->getStateUsing( - static function ($record): string { - try { - return \count($record->result['processed']); - } catch(\Exception $e) { - return 0; - } - } - ) - ->html(), - TextColumn::make('failed') - ->label(__('import.columns.failed')) - ->sortable() - ->searchable() - ->getStateUsing( - static function ($record): string { - try { - return \count($record->result['failed']); - } catch(\Exception $e) { - return 0; - } - } - ) - ->html(), - TextColumn::make('status') - ->label(__('import.columns.status')) - ->sortable() - ->searchable() - ->formatStateUsing(function ($state, $record) { - if ($state == 2 && \count($record->result['errors'])) { - $errors = ''; - foreach ($record->result['errors'] as $err) { - $errors .= __('import.' . $err); - } - - return $errors; - } - - return match ($state) { - 0 => __('import.status.pending'), - 1 => __('import.status.processing'), - 2 => '' . __('import.status.view') . '', - }; - }) - ->html(), - ]) - ->filters([ - // - ]) - ->actions([ - Tables\Actions\DeleteAction::make()->iconButton()->hidden(function ($record) { - return $record->status != 0; - }), - ]) - ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make(), - ]), - ]); - } - - public static function getRelations(): array - { - return [ - // - ]; - } - - public static function getPages(): array - { - return [ - 'index' => Pages\ListImports::route('/'), - 'create' => Pages\CreateImport::route('/create'), - 'view_report' => Pages\ViewImport::route('/{record}'), - // 'edit' => Pages\EditImport::route('/{record}/edit'), - ]; - } - - public static function getLabel(): ?string - { - return 'Import'; - } - - public static function getPluralLabel(): ?string - { - return 'Import'; - } - - public static function getNavigationBadge(): ?string - { - return (string) static::getModel()::whereStatus(0)->count(); - } - - public static function getEloquentQuery(): Builder - { - return parent::getEloquentQuery(); - } - - public static function canAccess(): bool - { - return false; - } -} diff --git a/app/Filament/Resources/ImportResource/Pages/CreateImport.php b/app/Filament/Resources/ImportResource/Pages/CreateImport.php deleted file mode 100644 index 65265639..00000000 --- a/app/Filament/Resources/ImportResource/Pages/CreateImport.php +++ /dev/null @@ -1,55 +0,0 @@ -schema([ - FileUpload::make('file') - ->preserveFilenames() - ->acceptedFileTypes(['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']), - ]); - } - - public function getTitle(): string - { - return __('imports.import_map_points_label'); - } - - protected function handleRecordCreation(array $data): Model - { - $record = new ImportExportModel(); - $record->file = $data['file']; - $record->type = 'map_points'; - $record->status = 0; - $record->created_by = auth()->user()->id; - $record->save(); - - return $record; - } -} diff --git a/app/Filament/Resources/ImportResource/Pages/EditImport.php b/app/Filament/Resources/ImportResource/Pages/EditImport.php deleted file mode 100644 index 57a9861b..00000000 --- a/app/Filament/Resources/ImportResource/Pages/EditImport.php +++ /dev/null @@ -1,21 +0,0 @@ -view_type = app()->request->get('show', 'processed'); - $data = $this->getRecord()->result[$this->view_type]; - - return $data; - } - - public function getSubHeading(): string | Htmlable - { - return \sprintf(__('imports.sub_heading'), $this->getRecord()->createdBy->fullname, $this->getRecord()->created_at, $this->getRecord()->finished_at); - } - - protected function getHeaderActions(): array - { - $actions = []; - $record = $this->getRecord(); - $failed = (isset($record->result['failed'])) ? \count($record->result['failed']) : 0; - $processed = (isset($record->result['processed'])) ? \count($record->result['processed']) : 0; - $actions = array_merge($actions, [ - Action::make('failed') - ->label(\sprintf(__('imports.not_imported'), $failed)) - ->icon('heroicon-m-check') - ->hidden(function () use ($failed) { - return $this->view_type == 'failed' || $failed == 0; - }) - ->url(fn (ImportExportModel $record): string => ImportResource::getUrl('view_report', ['record' => $record->id]) . '?show=failed') - ->color('danger'), - Action::make('processed') - ->label(\sprintf(__('imports.imported'), $processed)) - ->icon('heroicon-m-check') - ->hidden(function () use ($processed) { - return $this->view_type == 'processed' || $processed == 0; - }) - ->url(fn (ImportExportModel $record): string => ImportResource::getUrl('view_report', ['record' => $record->id]) . '?show=processed') - ->color('success'), - ]); - - return $actions; - } - - protected function getPostFormSchema(): array - { - return [ - TextInput::make('title') - ->required(), - ]; - } - - public function getBreadcrumb(): string - { - return static::$breadcrumb ?? __('filament-panels::resources/pages/view-record.breadcrumb'); - } - - public function getContentTabLabel(): ?string - { - return __('filament-panels::resources/pages/view-record.content.tab.label'); - } - - public function getTitle(): string | Htmlable - { - $record = $this->getRecord(); - - $title = __('imports.import_record_label') . $this->getRecord()->id; - - return new HtmlString($title); - } - - public function table(Table $table): Table - { - switch($this->view_type) { - case 'processed': - return $this->getProccesedTable($table); - break; - case 'failed': - return $this->getFailedTable($table); - break; - } - } - - public function getProccesedTable(Table $table): Table - { - return $table - ->query(MapPointModel::query()->whereIn('id', array_values($this->data))) - ->columns([ - - TextColumn::make('id') - ->label(__('map_points.id')) - ->formatStateUsing(function ($state) { - return '' . $state . ''; - }) - ->sortable() - ->searchable() - ->html(), - TextColumn::make('type.display_name') - ->label(__('map_points.point_type')) - ->searchable(), - TextColumn::make('managed_by') - ->label(__('map_points.managed_by')) - ->sortable() - ->searchable() - ->wrap(), - TextColumn::make('materials.getParent.icon') - ->label(__('map_points.materials')) - ->sortable() - ->searchable() - ->formatStateUsing(function (string $state, $record) { - $icons = collect(explode(',', $state))->unique(); - $state = '