From a07bcd3a5bdc567bfeea78dd8de0cea91f982ef5 Mon Sep 17 00:00:00 2001 From: Nurmuhammet Allanov Date: Sat, 25 Oct 2025 11:19:42 +0500 Subject: [PATCH] some progress on card balance --- .../Clusters/Cards/Cards/CardResource.php | 28 ++++++- app/Modules/CardBalance/CardBalanceModule.php | 64 ++++++++++++++++ .../Repositories/CardBalanceRepository.php | 75 +++++++++++++++++++ .../Views/card-balance-modal.blade.php | 68 +++++++++++++++++ .../CardBalance/Type/CardBalanceResponse.php | 57 ++++++++++++++ app/Modules/module-helpers.php | 60 +++++++++++++++ 6 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 app/Modules/CardBalance/CardBalanceModule.php create mode 100644 app/Modules/CardBalance/Repositories/CardBalanceRepository.php create mode 100644 app/Modules/CardBalance/Resources/Views/card-balance-modal.blade.php create mode 100644 app/Modules/CardBalance/Type/CardBalanceResponse.php diff --git a/app/Filament/Clusters/Cards/Cards/CardResource.php b/app/Filament/Clusters/Cards/Cards/CardResource.php index 3279dc2..bbbe624 100644 --- a/app/Filament/Clusters/Cards/Cards/CardResource.php +++ b/app/Filament/Clusters/Cards/Cards/CardResource.php @@ -6,7 +6,9 @@ use App\Filament\Clusters\Cards\Cards\Pages\ManageCards; 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 BackedEnum; +use Filament\Actions\Action; use Filament\Actions\BulkActionGroup; use Filament\Actions\DeleteAction; use Filament\Actions\DeleteBulkAction; @@ -19,6 +21,7 @@ use Filament\Schemas\Schema; use Filament\Support\Icons\Heroicon; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use Illuminate\Support\Str; class CardResource extends Resource { @@ -114,8 +117,29 @@ class CardResource extends Resource // ]) ->recordActions([ - EditAction::make(), - DeleteAction::make(), + Action::make('card_balance') + ->label(__('Card balance')) + ->icon('heroicon-m-credit-card') + ->modalContent(function (Card $record) { + /** @var \App\Modules\CardBalance\Type\CardBalanceResponse */ + $data = CardBalanceRepository::make()->fetchCardBalance( + passport_serie: user()->getOption('passport_serie'), + passport_id: user()->getOption('passport_id'), + card_masked: Str::mask($record->number, '*', 6, 6), + card_expire_date: $record->month.'/'.substr($record->year, 2), + ); + + if ($data->errCode != 0) { + return $data->message; + } + + return view('module.card-balance::card-balance-modal', compact('data')); + }), + + EditAction::make() + ->label(''), + DeleteAction::make() + ->label(''), ]) ->toolbarActions([ BulkActionGroup::make([ diff --git a/app/Modules/CardBalance/CardBalanceModule.php b/app/Modules/CardBalance/CardBalanceModule.php new file mode 100644 index 0000000..4250441 --- /dev/null +++ b/app/Modules/CardBalance/CardBalanceModule.php @@ -0,0 +1,64 @@ +enabled; + } + + /** + * Disable module + */ + public function disable(): void + { + $this->enabled = false; + } + + /** + * Enable module + */ + public function enable(): void + { + $this->enabled = true; + } + + /** + * Check if module has a filament resource + */ + public function hasFilamentResource(): bool + { + return false; + } + + /** + * Get module composer requirements + */ + public function getComposerRequirements(): array + { + return []; + } + + /** + * Get module composer suggestions + */ + public function getComposerSuggestions(): array + { + return []; + } +} diff --git a/app/Modules/CardBalance/Repositories/CardBalanceRepository.php b/app/Modules/CardBalance/Repositories/CardBalanceRepository.php new file mode 100644 index 0000000..bd84abb --- /dev/null +++ b/app/Modules/CardBalance/Repositories/CardBalanceRepository.php @@ -0,0 +1,75 @@ +fetchCardBalance( + passport_serie: user()->getOption('passport_serie'), + passport_id: user()->getOption('passport_id'), + card_masked: Str::mask($record->number, '*', 6, 6), + card_expire_date: $record->month.'/'.substr($record->year, 2), + ); + + if ($data->errCode != 0) { + return $data->message; + } + + return view('module.card-balance::card-balance-modal', compact('data')); + } + + /** + * Fetch card balance + * + * @param string|int $passport_serie + * @param string|int $passport_id + * @param string $card_masked + * @param string $card_expire_date + */ + public function fetchCardBalance($passport_serie, $passport_id, $card_masked, $card_expire_date): object + { + $curl = curl_init(); + + curl_setopt_array($curl, [ + CURLOPT_URL => 'http://10.3.158.102:9999/api/clientcardinfo', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => sprintf('{ + "idSeria": "%s", + "idNo": "%s", + "cardMaskNumber": "%s", + "expDate": "%s" + }', $passport_serie, $passport_id, $card_masked, $card_expire_date), + CURLOPT_HTTPHEADER => [ + 'Authorization: Basic dGJ1c2VyOlFBWndzeDEyMw==', + 'Content-Type: application/json', + ], + ]); + + $response = curl_exec($curl); + + curl_close($curl); + + return Str::isJson($response) + ? json_decode($response) + : emptyClass(errCode: 1, message: 'Connection issue to VP'); + } +} diff --git a/app/Modules/CardBalance/Resources/Views/card-balance-modal.blade.php b/app/Modules/CardBalance/Resources/Views/card-balance-modal.blade.php new file mode 100644 index 0000000..48f05dd --- /dev/null +++ b/app/Modules/CardBalance/Resources/Views/card-balance-modal.blade.php @@ -0,0 +1,68 @@ + + + + + + Card Balance + + + +
+
+
+
+
+ +
+
+

{{ $data->depName }}

+

{{ $data->cardName }}

+
+
+
+
+

+ {{ __('Card number') }} +

+
+

+ {{ $data->cardMaskNumber }} +

+
+
+
+
+

+ {{ __('Card holder name') }} +

+

+ {{ $data->clientName }} +

+
+
+

+ {{ __('Expiry date') }} +

+

+ {{ $data->expDate }} +

+
+
+
+
+

+ {{ __('Money Balance') }} +

+
+

+ {{ $data->balance }} {{ $data->valCode }} +

+
+
+
+
+
+ + diff --git a/app/Modules/CardBalance/Type/CardBalanceResponse.php b/app/Modules/CardBalance/Type/CardBalanceResponse.php new file mode 100644 index 0000000..74a81ba --- /dev/null +++ b/app/Modules/CardBalance/Type/CardBalanceResponse.php @@ -0,0 +1,57 @@ + */ + public array $transactions; +} diff --git a/app/Modules/module-helpers.php b/app/Modules/module-helpers.php index c18de8b..960fd60 100644 --- a/app/Modules/module-helpers.php +++ b/app/Modules/module-helpers.php @@ -45,3 +45,63 @@ function emptyModule(): ModuleContract { return modular()->emptyModule(); } + +/** + * Create an anonymous class that acts as a dynamic object. + * + * @param mixed ...$arguments Key-value pairs passed as an associative array. + * @return object Anonymous class instance with dynamic properties. + */ +function emptyClass(...$arguments): object +{ + /** + * @var array $arguments + */ + return new class($arguments) + { + /** + * Internal data storage. + * + * @var array + */ + private array $data = []; + + /** + * Constructor that sets properties. + * + * @param array $props + */ + public function __construct(array $props) + { + foreach ($props as $key => $value) { + $this->data[$key] = $value; + } + } + + /** + * Magic getter. + * + * @return mixed|null + */ + public function __get(string $key): mixed + { + return $this->data[$key] ?? null; + } + + /** + * Magic setter. + */ + public function __set(string $key, mixed $value): void + { + $this->data[$key] = $value; + } + + /** + * Magic isset. + */ + public function __isset(string $key): bool + { + return isset($this->data[$key]); + } + }; +}