diff --git a/app/Filament/Clusters/Cards/Cards/CardResource.php b/app/Filament/Clusters/Cards/Cards/CardResource.php index b22e9e7..fbdb024 100644 --- a/app/Filament/Clusters/Cards/Cards/CardResource.php +++ b/app/Filament/Clusters/Cards/Cards/CardResource.php @@ -7,6 +7,7 @@ use App\Filament\Clusters\Cards\CardsCluster; use App\Modules\AppHelpers\Repositories\DateHelper; use App\Modules\Card\Models\Card; use App\Modules\CardBalance\Repositories\CardBalanceRepository; +use App\Modules\CardRequisite\Repositories\CardRequisiteRepository; use App\Modules\CardTransaction\Repositories\CardTransactionRepository; use BackedEnum; use Filament\Actions\Action; @@ -124,15 +125,15 @@ class CardResource extends Resource ->recordActions([ Action::make('card_balance') ->label(__('Card balance')) - ->icon('heroicon-m-credit-card') + ->icon('heroicon-o-credit-card') ->requiresConfirmation(false) ->modal() ->modalContent(fn (Card $record): View => CardBalanceRepository::make()->showCardBalance($record)) ->modalFooterActions([]), - Action::make('card_transaction') - ->label(__('Card transaction')) - ->icon('heroicon-m-arrows-right-left') + Action::make('card_transactions') + ->label(__('Card transactions')) + ->icon('heroicon-o-arrows-right-left') ->requiresConfirmation() ->modalIcon('heroicon-m-arrows-right-left') ->schema([ @@ -148,11 +149,17 @@ class CardResource extends Resource ->required() ->beforeOrEqual('today'), ]) - ->openUrlInNewTab() ->action( fn (array $data, Card $record, Component $livewire) => CardTransactionRepository::make()->downloadCardTransaction($data, $record, $livewire) ), + Action::make('card_requisite') + ->label(__('Card requisite')) + ->icon('heroicon-o-document-text') + ->requiresConfirmation() + ->modalIcon('heroicon-o-document-text') + ->action(fn (Card $record, Component $livewire) => CardRequisiteRepository::make()->downloadCardRequisite($record, $livewire)), + EditAction::make() ->label(''), DeleteAction::make() diff --git a/app/Modules/CardRequisite/CardRequisiteModule.php b/app/Modules/CardRequisite/CardRequisiteModule.php index 96cb916..e2dc866 100644 --- a/app/Modules/CardRequisite/CardRequisiteModule.php +++ b/app/Modules/CardRequisite/CardRequisiteModule.php @@ -2,6 +2,8 @@ namespace App\Modules\CardRequisite; +use App\Modules\Core\ModulePackage; +use App\Modules\Core\ModulePackageType; use App\Modules\Makeable; use App\Modules\ModuleContract; @@ -51,7 +53,19 @@ class CardRequisiteModule implements ModuleContract */ public function getComposerRequirements(): array { - return []; + return [ + new ModulePackage( + type: ModulePackageType::MODULE, + name: 'CardTransaction', + message: 'Required for API', + ), + new ModulePackage( + type: ModulePackageType::PACKAGE, + name: 'phpoffice/phpword', + message: 'Required for docx file generation', + version: 'dev-master', + ), + ]; } /** diff --git a/app/Modules/CardRequisite/Repositories/CardRequisiteRepository.php b/app/Modules/CardRequisite/Repositories/CardRequisiteRepository.php index 000870a..75e2fee 100644 --- a/app/Modules/CardRequisite/Repositories/CardRequisiteRepository.php +++ b/app/Modules/CardRequisite/Repositories/CardRequisiteRepository.php @@ -2,9 +2,99 @@ namespace App\Modules\CardRequisite\Repositories; +use App\Modules\Card\Models\Card; +use App\Modules\CardTransaction\Repositories\CardTransactionRepository; use App\Modules\Makeable; +use Filament\Notifications\Notification; +use Illuminate\Support\Str; +use Livewire\Component; class CardRequisiteRepository { use Makeable; + + public function downloadCardRequisite(Card $record, Component $livewire) + { + /** @var \App\Modules\CardTransaction\Types\CardTransactionResponse */ + $response = $this->fetchApi($record); + + if ($response->errCode != 0) { + Notification::make() + ->danger() + ->title($response->message) + ->send(); + + return; + } + + $path = $this->generateFile($record, $response); + + // return ActionResponse::download( + // name: 'kart-rekwizit.docx', + // url: url($path) + // ); + } + + /** + * Fetch api + * + * @return object + */ + public function fetchApi(Card $record) + { + $date = today()->format('d.m.Y'); + + $response = CardTransactionRepository::make()->fetchApi( + passport_serie: user()->passport_serie(), + passport_id: user()->passport_id(), + card_number_masked: Str::mask($record->number, '*', 6, 6), + card_expire_date: $record->month.'/'.substr($record->year, 2), + start_date: $date, + end_date: $date, + ); + + return Str::isJson($response) + ? json_decode($response) + : emptyClass(errCode: 1, message: 'Connection issue to VP'); + } + + /** + * Generate file + * + * @param \App\Models\Order\Card\Requisite\CardRequisite $model + * @param \App\Nova\Resources\Order\Card\CardTransaction\Actions\ResponseTypes\AzatApiClientInfoAllResponse $data + * @return string + */ + public function generateFile($model, $data) + { + $doc_path = app_path('Nova/Resources/Order/Card/Requisite/Docs/card-requisite.docx'); + + $templateProcessor = new TemplateProcessor($doc_path); + $templateProcessor->setValues([ + 'year' => date('Y'), + 'name' => $data->clientName, + 'contract' => $data->cardAccountNumber, + 'bank' => $data->depName, + 'hasap' => $data->accountNumber, + 'sb' => $data->inn, + 'bab' => $data->mfo, + 'card_type' => $data->cardName, + 'card_number' => $data->cardPan, + 'phone' => $data->mobilPhone ?? '-', + 'contract_date' => '---YOK---', + 'card_order_date' => '---YOK---', + 'card_given_date' => '---YOK---', + ]); + + $unique_folder_name = Str::snake(str_replace(':', '-', $model->created_at->toDateTimeString())); + $dir = public_path("files/card-requisite/{$unique_folder_name}"); + + File::makeDirectory($dir, 0777, true, true); + + $filePath = $dir."/{$model->id}.docx"; + + $templateProcessor->saveAs($filePath); + + return "files/card-requisite/{$unique_folder_name}/{$model->id}.docx"; + } } diff --git a/app/Modules/CardRequisite/Resources/Docs/card-requisite.docx b/app/Modules/CardRequisite/Resources/Docs/card-requisite.docx new file mode 100644 index 0000000..08e1e45 Binary files /dev/null and b/app/Modules/CardRequisite/Resources/Docs/card-requisite.docx differ diff --git a/app/Modules/ModuleRepository.php b/app/Modules/ModuleRepository.php index 0cfbf33..f2172bb 100644 --- a/app/Modules/ModuleRepository.php +++ b/app/Modules/ModuleRepository.php @@ -126,4 +126,14 @@ class ModuleRepository { return $this->allModules; } + + /** + * Check if module exists + * + * @param string $moduleName + */ + public function moduleExists(string $moduleName): bool + { + return $this->modules->contains(fn (BaseModule $module) => $module->name === $moduleName); + } } diff --git a/app/Modules/ModuleServiceProvider.php b/app/Modules/ModuleServiceProvider.php index 9a082f0..cd4e5fb 100644 --- a/app/Modules/ModuleServiceProvider.php +++ b/app/Modules/ModuleServiceProvider.php @@ -2,6 +2,10 @@ namespace App\Modules; +use App\Modules\Core\ModulePackage; +use App\Modules\Core\ModulePackageType; +use Composer\Composer; +use Composer\InstalledVersions; use Illuminate\Contracts\Foundation\Application; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; @@ -57,9 +61,25 @@ class ModuleServiceProvider extends ServiceProvider */ public function verifyModuleComposerRequirements(BaseModule $module): void { - // foreach ($module->app->getComposerRequirements() as $requirement) { + foreach ($module->app->getComposerRequirements() as $package) { + if ($package->type === ModulePackageType::PACKAGE) { + if (! InstalledVersions::isInstalled($package->name)) { + abort( + code: 500, + message: "{$package->name} must be installed (module: {$module->name})" + ); + } + } - // } + if ($package->type === ModulePackageType::MODULE) { + if (! module_exists($package->name)) { + abort( + code: 500, + message: "{$package->name} module must be installed (module: {$module->name})" + ); + } + } + } } /** diff --git a/app/Modules/module-helpers.php b/app/Modules/module-helpers.php index 960fd60..73a734c 100644 --- a/app/Modules/module-helpers.php +++ b/app/Modules/module-helpers.php @@ -46,6 +46,14 @@ function emptyModule(): ModuleContract return modular()->emptyModule(); } +/** + * Module exists + */ +function module_exists(string $moduleName) +{ + return modular()->moduleExists($moduleName); +} + /** * Create an anonymous class that acts as a dynamic object. *