diff --git a/app/Models/Order/Card/Requisite/CardRequisite.php b/app/Models/Order/Card/Requisite/CardRequisite.php index 4f2406f..a8cf1da 100644 --- a/app/Models/Order/Card/Requisite/CardRequisite.php +++ b/app/Models/Order/Card/Requisite/CardRequisite.php @@ -10,6 +10,33 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; +/** + * @property int $int + * @property string $unique_id + * @property string $card_type_id + * @property string $card_number + * @property string $card_year + * @property string $card_month + * @property string $region + * @property string $branch_id + * @property string $customer_name + * @property string $customer_surname + * @property string $customer_patronic_name + * @property string $born_at + * @property string $phone + * @property string $passport_serie + * @property string $passport_id + * @property string $status + * @property string $passport_one + * @property string $passport_two + * @property string $passport_three + * @property string $passport_four + * @property string $notes + * @property string $user_id + * @property string $ready_files + * @property \Illuminate\Support\Carbon $created_at + * @property \Illuminate\Support\Carbon $updated_at +*/ class CardRequisite extends Model { use HasFactory; diff --git a/app/Nova/Resources/Order/Card/Requisite/Actions/DownloadCardRequisite.php b/app/Nova/Resources/Order/Card/Requisite/Actions/DownloadCardRequisite.php new file mode 100644 index 0000000..6bbc171 --- /dev/null +++ b/app/Nova/Resources/Order/Card/Requisite/Actions/DownloadCardRequisite.php @@ -0,0 +1,108 @@ +first(); + + /** @var \App\Nova\Resources\Order\Card\CardTransaction\Actions\ResponseTypes\AzatApiClientInfoAllResponse */ + $data = $this->fetchApi($model); + + if ($data->errCode != 0) { + return ActionResponse::danger($data->message); + } + + $path = $this->generateFile($model, $data); + + return ActionResponse::download( + name: 'card-requisite.docx', + url: url($path) + ); + } + + /** + * Get the fields available on the action. + * + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @return array + */ + public function fields(NovaRequest $request) + { + return []; + } + + /** + * Fetch api + * + * @param \App\Models\Order\Card\Requisite\CardRequisite $model + */ + public function fetchApi($model) + { + $date = today()->format('d.m.Y'); + + $response = DownloadCardTransaction::make()->fetchApi( + passport_serie: $model->passport_serie, + passport_id: $model->passport_id, + card_number_masked: Str::mask($model->card_number, '*', 6, 6), + card_expire_date: $model->card_month.'/'.substr($model->card_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 @param \App\Models\Order\Card\Requisite\CardRequisite $model + */ + public function generateFile($model) + { + $doc_path = app_path('Nova/Resources/Order/Card/Requisite/Docs/card-requisite.docx'); + + $templateProcessor = new TemplateProcessor($doc_path); + $templateProcessor->setValues([ + 'year' => date('Y'), + ]); + + $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/Nova/Resources/Order/Card/Requisite/CardRequisite.php b/app/Nova/Resources/Order/Card/Requisite/CardRequisite.php index e6003ee..0f125ce 100644 --- a/app/Nova/Resources/Order/Card/Requisite/CardRequisite.php +++ b/app/Nova/Resources/Order/Card/Requisite/CardRequisite.php @@ -4,10 +4,12 @@ namespace App\Nova\Resources\Order\Card\Requisite; use App\Models\Branch\Branch; use App\Models\Order\Card\Requisite\CardRequisite as CardRequisiteModel; +use App\Modules\DateHelper\Repositories\DateHelperRepository; use App\Nova\Filters\RegionFilter; use App\Nova\Filters\StatusFilter; use App\Nova\Nova; use App\Nova\Resource; +use App\Nova\Resources\Order\Card\Requisite\Actions\DownloadCardRequisite; use App\Nova\Resources\Order\Card\Requisite\Concerns\CardRequisiteFieldsForDetail; use App\Nova\Resources\Order\Card\Requisite\Concerns\CardRequisiteFieldsForIndex; use App\Repos\Order\Card\CardOrderRepo; @@ -205,19 +207,23 @@ class CardRequisite extends Resource ->canSeeWhen('systemUser', $this), new Panel(__('Card'), [ - Select::make(__('Card type'), 'card_type_id') - ->displayUsingLabels() - ->fullWidth() - ->searchable() - ->options(CardTypeRepo::values()) - ->size('w-1/2') - ->rules('required'), - NovaInputmask::make(__('Card number'), 'card_number') ->mask('9999 9999 9999 9999') ->storeRawValue() ->size('w-1/2') ->rules('required', 'int', 'digits:16'), + + Select::make(__('Card').' '.__('Expiration month'), 'card_month') + ->searchable() + ->options(DateHelperRepository::staticNumberMonths()) + ->size('md:w-1/4') + ->rules('required'), + + Select::make(__('Card').' '.__('Expiration year'), 'card_year') + ->searchable() + ->options(DateHelperRepository::staticNumberYears()) + ->size('md:w-1/4') + ->rules('required'), ]), new Panel(__('Location'), [ @@ -301,13 +307,6 @@ class CardRequisite extends Resource ->creationRules('required') ->updateRules('nullable'), ]), - - new Panel(__('Ready files'), [ - File::make(__('Card requisite'), 'ready_files') - ->rules('max:2048', 'mimes:doc,docx,rtf,pdf,jpg,png,jpeg') - ->hideWhenCreating() - ->canSeeWhen('systemUser', $this), - ]), ]; } @@ -325,4 +324,18 @@ class CardRequisite extends Resource new StatusFilter, ]; } + + /** + * Actions + * + * @return array + */ + public function actions(NovaRequest $request): array + { + return [ + DownloadCardRequisite::make() + ->icon('arrow-down-tray') + ->sole(), + ]; + } } diff --git a/app/Nova/Resources/Order/Card/Requisite/Concerns/CardRequisiteFieldsForDetail.php b/app/Nova/Resources/Order/Card/Requisite/Concerns/CardRequisiteFieldsForDetail.php index 0b4cd7a..e28ff77 100644 --- a/app/Nova/Resources/Order/Card/Requisite/Concerns/CardRequisiteFieldsForDetail.php +++ b/app/Nova/Resources/Order/Card/Requisite/Concerns/CardRequisiteFieldsForDetail.php @@ -2,6 +2,7 @@ namespace App\Nova\Resources\Order\Card\Requisite\Concerns; +use App\Modules\DateHelper\Repositories\DateHelperRepository; use App\Nova\Resources\Branch\Branch; use App\Nova\Resources\Order\Card\CardType; use App\Nova\User; @@ -51,11 +52,15 @@ class CardRequisiteFieldsForDetail BelongsTo::make(__('Created by').': ', 'user', User::class), new Panel(__('Card'), [ - BelongsTo::make(__('Card type'), 'cardType', CardType::class), - NovaInputmask::make(__('Card number'), 'card_number') ->mask('9999 9999 9999 9999') ->storeRawValue(), + + Select::make(__('Card').' '.__('Expiration month'), 'card_month') + ->options(DateHelperRepository::staticNumberMonths()), + + Select::make(__('Card').' '.__('Expiration year'), 'card_year') + ->options(DateHelperRepository::staticNumberYears()) ]), new Panel(__('Location'), [ @@ -97,10 +102,6 @@ class CardRequisiteFieldsForDetail Image::make(__('Passport (page 8-9)'), 'passport_three'), Image::make(__('Passport (page 32)'), 'passport_four'), ]), - - new Panel(__('Ready files'), [ - File::make(__('Card requisite'), 'ready_files'), - ]), ]; } } diff --git a/app/Nova/Resources/Order/Card/Requisite/Docs/card-requisite.docx b/app/Nova/Resources/Order/Card/Requisite/Docs/card-requisite.docx new file mode 100644 index 0000000..09f6d63 Binary files /dev/null and b/app/Nova/Resources/Order/Card/Requisite/Docs/card-requisite.docx differ diff --git a/app/Nova/Resources/Order/Card/Requisite/Docs/~$rd-requisite.docx b/app/Nova/Resources/Order/Card/Requisite/Docs/~$rd-requisite.docx new file mode 100644 index 0000000..9070d56 Binary files /dev/null and b/app/Nova/Resources/Order/Card/Requisite/Docs/~$rd-requisite.docx differ diff --git a/composer.json b/composer.json index 9b66332..6012eea 100644 --- a/composer.json +++ b/composer.json @@ -33,6 +33,7 @@ "outl1ne/nova-grid": "@dev", "outl1ne/nova-simple-repeatable": "^2.2", "outl1ne/nova-translatable": "^2.2", + "phpoffice/phpword": "dev-master", "spatie/laravel-backup": "^8.4", "spatie/laravel-medialibrary": "^11.9", "spatie/laravel-permission": "^6.1", diff --git a/composer.lock b/composer.lock index b6f4478..c18d5c1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7a2dbd9905ac906785253c58903ea32b", + "content-hash": "d22b828bf01fdfbf3cafac9bd1d57ac0", "packages": [ { "name": "adoy/fastcgi-client", @@ -5334,6 +5334,167 @@ }, "time": "2020-10-15T08:29:30+00:00" }, + { + "name": "phpoffice/math", + "version": "0.2.0", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/Math.git", + "reference": "fc2eb6d1a61b058d5dac77197059db30ee3c8329" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/Math/zipball/fc2eb6d1a61b058d5dac77197059db30ee3c8329", + "reference": "fc2eb6d1a61b058d5dac77197059db30ee3c8329", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xml": "*", + "php": "^7.1|^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.88 || ^1.0.0", + "phpunit/phpunit": "^7.0 || ^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\Math\\": "src/Math/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Progi1984", + "homepage": "https://lefevre.dev" + } + ], + "description": "Math - Manipulate Math Formula", + "homepage": "https://phpoffice.github.io/Math/", + "keywords": [ + "MathML", + "officemathml", + "php" + ], + "support": { + "issues": "https://github.com/PHPOffice/Math/issues", + "source": "https://github.com/PHPOffice/Math/tree/0.2.0" + }, + "time": "2024-08-12T07:30:45+00:00" + }, + { + "name": "phpoffice/phpword", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/PHPWord.git", + "reference": "6ca8c9ff67e0ea7729973b7b3a33626febad6628" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/PHPWord/zipball/6ca8c9ff67e0ea7729973b7b3a33626febad6628", + "reference": "6ca8c9ff67e0ea7729973b7b3a33626febad6628", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-gd": "*", + "ext-json": "*", + "ext-xml": "*", + "ext-zip": "*", + "php": "^7.1|^8.0", + "phpoffice/math": "^0.2" + }, + "require-dev": { + "dompdf/dompdf": "^2.0 || ^3.0", + "ext-libxml": "*", + "friendsofphp/php-cs-fixer": "^3.3", + "mpdf/mpdf": "^7.0 || ^8.0", + "phpmd/phpmd": "^2.13", + "phpstan/phpstan": "^0.12.88 || ^1.0.0", + "phpstan/phpstan-phpunit": "^1.0 || ^2.0", + "phpunit/phpunit": ">=7.0", + "symfony/process": "^4.4 || ^5.0", + "tecnickcom/tcpdf": "^6.5" + }, + "suggest": { + "dompdf/dompdf": "Allows writing PDF", + "ext-xmlwriter": "Allows writing OOXML and ODF", + "ext-xsl": "Allows applying XSL style sheet to headers, to main document part, and to footers of an OOXML template" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\PhpWord\\": "src/PhpWord" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-only" + ], + "authors": [ + { + "name": "Mark Baker" + }, + { + "name": "Gabriel Bull", + "email": "me@gabrielbull.com", + "homepage": "http://gabrielbull.com/" + }, + { + "name": "Franck Lefevre", + "homepage": "https://rootslabs.net/blog/" + }, + { + "name": "Ivan Lanin", + "homepage": "http://ivan.lanin.org" + }, + { + "name": "Roman Syroeshko", + "homepage": "http://ru.linkedin.com/pub/roman-syroeshko/34/a53/994/" + }, + { + "name": "Antoine de Troostembergh" + } + ], + "description": "PHPWord - A pure PHP library for reading and writing word processing documents (OOXML, ODF, RTF, HTML, PDF)", + "homepage": "https://phpoffice.github.io/PHPWord/", + "keywords": [ + "ISO IEC 29500", + "OOXML", + "Office Open XML", + "OpenDocument", + "OpenXML", + "PhpOffice", + "PhpWord", + "Rich Text Format", + "WordprocessingML", + "doc", + "docx", + "html", + "odf", + "odt", + "office", + "pdf", + "php", + "reader", + "rtf", + "template", + "template processor", + "word", + "writer" + ], + "support": { + "issues": "https://github.com/PHPOffice/PHPWord/issues", + "source": "https://github.com/PHPOffice/PHPWord/tree/master" + }, + "time": "2025-02-20T20:19:21+00:00" + }, { "name": "phpoption/phpoption", "version": "1.9.3", @@ -14014,7 +14175,8 @@ "stability-flags": { "eolica/nova-locale-switcher": 20, "nurmuhammet/nova-custom-html": 20, - "outl1ne/nova-grid": 20 + "outl1ne/nova-grid": 20, + "phpoffice/phpword": 20 }, "prefer-stable": true, "prefer-lowest": false, diff --git a/database/migrations/2025_05_29_151031_card_requisites_card_type_id_null.php b/database/migrations/2025_05_29_151031_card_requisites_card_type_id_null.php new file mode 100644 index 0000000..627b788 --- /dev/null +++ b/database/migrations/2025_05_29_151031_card_requisites_card_type_id_null.php @@ -0,0 +1,39 @@ +string('card_month')->nullable(); + $table->string('card_year')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::statement(' + ALTER TABLE "public"."card_requisites" ALTER COLUMN "card_type_id" SET NOT NULL; + '); + + Schema::table('card_requisites', function (Blueprint $table) { + $table->dropColumn('card_month'); + $table->dropColumn('card_year'); + }); + } +};