diff --git a/app/Modules/SberPaymentOrder/Nova/Resources/Concerns/SberPaymentOrderFieldsForDetail.php b/app/Modules/SberPaymentOrder/Nova/Resources/Concerns/SberPaymentOrderFieldsForDetail.php index 4284990..de59064 100644 --- a/app/Modules/SberPaymentOrder/Nova/Resources/Concerns/SberPaymentOrderFieldsForDetail.php +++ b/app/Modules/SberPaymentOrder/Nova/Resources/Concerns/SberPaymentOrderFieldsForDetail.php @@ -2,7 +2,7 @@ namespace App\Modules\SberPaymentOrder\Nova\Resources\Concerns; -use App\Modules\VisaMasterPaymentOrder\Nova\Resources\VisaMasterPaymentOrderFileFields; +use App\Modules\SberPaymentOrder\Nova\Resources\SberPaymentOrderFileFields; use App\Nova\Resources\Branch\Branch; use App\Repos\Order\OrderRepo; use App\Repos\System\Settings\Legal\PassportRepo; @@ -137,8 +137,8 @@ class SberPaymentOrderFieldsForDetail ])->maxRows(1)->minRows(1)->rules('required'), ]), - new Panel(__('Reciver files'), VisaMasterPaymentOrderFileFields::reciverFiles()), - new Panel(__('Sender files'), VisaMasterPaymentOrderFileFields::senderFiles()), + new Panel(__('Reciver files'), SberPaymentOrderFileFields::reciverFiles()), + new Panel(__('Sender files'), SberPaymentOrderFileFields::senderFiles()), ]; } } diff --git a/app/Modules/TuitionPaymentOrder/Database/Migrations/2024_09_08_214728_create_tuitionpaymentorders_table.php b/app/Modules/TuitionPaymentOrder/Database/Migrations/2024_09_08_214728_create_tuitionpaymentorders_table.php new file mode 100644 index 0000000..69a3fec --- /dev/null +++ b/app/Modules/TuitionPaymentOrder/Database/Migrations/2024_09_08_214728_create_tuitionpaymentorders_table.php @@ -0,0 +1,48 @@ +id(); + $table->string('unique_id')->nullable()->unique(); + + $table->string('type')->nullable(); + $table->string('passport_name')->nullable(); + $table->string('passport_surname')->nullable(); + $table->string('phone')->nullable(); + $table->string('email')->nullable(); + $table->string('region')->nullable(); + + $table->foreignId('branch_id')->nullable()->constrained('branches')->cascadeOnDelete(); + $table->foreignId('user_id')->nullable()->constrained('users')->cascadeOnDelete(); + + $table->string('address')->nullable(); + + $table->json('sender_datas')->nullable(); + $table->json('payment_reciever')->nullable(); + + $table->json('documents')->nullable(); + + $table->string('status')->nullable(); + $table->string('notes')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('tuition_payment_orders'); + } +}; diff --git a/app/Modules/TuitionPaymentOrder/Models/TuitionPaymentOrder.php b/app/Modules/TuitionPaymentOrder/Models/TuitionPaymentOrder.php new file mode 100644 index 0000000..ed4faca --- /dev/null +++ b/app/Modules/TuitionPaymentOrder/Models/TuitionPaymentOrder.php @@ -0,0 +1,146 @@ + + */ + protected $casts = [ + 'sender_datas' => 'array', + 'payment_reciever' => 'array', + ]; + + /** + * Media collections + */ + public function registerMediaCollections(): void + { + foreach (static::reciverFiles() as $reciverFile) { + $this->addMediaCollection($reciverFile['code'])->singleFile(); + } + + foreach (static::senderFiles() as $senderFile) { + $this->addMediaCollection($senderFile['code'])->singleFile(); + } + } + + /** + * Branch + */ + public function branch(): BelongsTo + { + return $this->belongsTo(Branch::class); + } + + /** + * Required files + */ + public static function reciverFiles(): array + { + return [ + [ + 'required' => true, + 'code' => 'unv_contract', + 'name' => 'Talybyň ýokary okuw mekdebi bilen baglaşan şertnamasy (asyl we göçürme nusgasy)', + ], + [ + 'required' => false, + 'code' => 'unv_semester_invoice', + 'name' => 'Okuw mekdebinde degişli okuw döwri üçin tölemäge degişli hasap-faktura ýa-da inwoýs (asyl we göçürme nusgasy)', + ], + [ + 'required' => false, + 'code' => 'student_card', + 'name' => 'Talybyň “Talyplyk şahadatnamasy” (göçürme nusgasy)', + ], + [ + 'required' => false, + 'code' => 'document_stating_he_is_studying', + 'name' => 'Talybyň daşary ýurt döwletiniň ýokary okuw mekdebinde okaýandygy baradaky güwänamasy', + ], + [ + 'required' => false, + 'code' => 'passport_local', + 'name' => 'Talyba degişli Türkmenistanyň raýatynyň (içki milli) pasportynyň asyl görnüşi we göçürmesi', + ], + [ + 'required' => false, + 'code' => 'passport_international', + 'name' => 'Talybyň Türkmenistandan çykmak we Türkmenistana girmek üçin (zagran) pasportynyň (şol sanda talybyň Türkmenistandan çykmak we Türkmenistana girmek üçin pasportyndaky daşary ýurtda galyp okap bilýändigi baradaky berlen möhleti hereket edýän rugsatnamasynyň (wizasynyň) hem-de ýurda girmek we çykmak baradaky seneli ştampyň bellenen sahypalarynyň) göçürmesi', + ], + [ + 'required' => false, + 'code' => 'document_stating_he_is_studying_2', + 'name' => 'Goşmaça resminamalar (şol sanda, talybyň daşary ýurt döwletiniň ýokary okuw mekdebinde okaýandygy baradaky güwänamasyndaky maglumatyň doly takyk däl ýagdaýynda takyk däl maglumatyň sebäpleri baradaky daşary ýurt döwletiniň ýokary okuw mekdebinden haty)', + ], + ]; + } + + /** + * Sender files + */ + public static function senderFiles(): array + { + return [ + [ + 'required' => true, + 'code' => 'passport_local', + 'name' => 'Ugradyja degişli Türkmenistanyň raýatynyň (içki milli) pasportynyň asyl görnüşi we göçürmesi ', + ], + + [ + 'required' => false, + 'code' => 'passport_international', + 'name' => 'Ugradyja degişli Türkmenistandan çykmak we Türkmenistana girmek üçin pasportynyň asyl görnüşi we göçürmesi ', + ], + + [ + 'required' => false, + 'code' => 'travel_stamp_on_passport', + 'name' => 'Ugradyja degişli Türkmenistandan çykmak we Türkmenistana girmek üçin (zagran) pasportynyň (şol sanda talybyň Türkmenistandan çykmak we Türkmenistana girmek üçin pasportyndaky daşary ýurtda galyp okap bilýändigi baradaky berlen möhleti hereket edýän rugsatnamasynyň (wizasynyň) hem-de ýurda girmek we çykmak baradaky seneli ştampyň bellenen sahypalarynyň) göçürmesi', + ], + [ + 'required' => false, + 'code' => 'proof_of_kinship', + 'name' => 'Ugradyjynyň we kabul edijiniň (talybyň) özara garyndaşlyk derejesini tassyklaýjy resminamalarynyň göçürmesi ', + ], + + [ + 'required' => false, + 'code' => 'passport_local_old', + 'name' => 'Ugradyjy we kabul ediji (talyp) 2015-nji ýyldan soňra Türkmenistanyň raýatynyň pasportyny ikinji gezek alan bolsa, onda birinji gezek alan pasportynyň seriýasy baradaky maglumaty ', + ], + + [ + 'required' => false, + 'code' => 'passport_local_old_replacement', + 'name' => 'Ugradyjy we kabul ediji (talyp) 2015-nji ýyldan soňra Türkmenistanyň raýatynyň pasportyny ikinji gezek alandan soňra birinji gezek alan pasportynyň seriýasy baradaky maglumaty bilmeýän bolsa, onda polisiýanyň degişli edaralaryndan birinji alan pasportynyň seriýasy baradaky güwänamasy ', + ], + + ]; + } +} diff --git a/app/Modules/TuitionPaymentOrder/Nova/Resources/Concerns/TuitionPaymentOrderFieldsForDetail.php b/app/Modules/TuitionPaymentOrder/Nova/Resources/Concerns/TuitionPaymentOrderFieldsForDetail.php new file mode 100644 index 0000000..96e78ae --- /dev/null +++ b/app/Modules/TuitionPaymentOrder/Nova/Resources/Concerns/TuitionPaymentOrderFieldsForDetail.php @@ -0,0 +1,144 @@ +hideFromDetail(), + + Hidden::make('user_id') + ->default(auth()->id()) + ->hideWhenUpdating(), + + Text::make(__('ID'), 'unique_id') + ->exceptOnForms(), + + Select::make(__('Status'), 'status') + ->displayUsingLabels() + ->searchable() + ->options(OrderRepo::statusValues()) + ->default(OrderRepo::defaultStatus()) + ->fullWidth() + ->hideFromDetail() + ->rules('required') + ->canSeeWhen('systemUser', $resource), + + Badge::make(__('Status'), 'status') + ->map(OrderRepo::statusClasses()) + ->addTypes([ + 'primary' => 'dark:bg-gray-900 bg-gray-600 text-white', + ]) + ->labels(OrderRepo::statusValues()) + ->withIcons() + ->icons(OrderRepo::statusIcons()), + + Text::make(__('Note'), 'notes') + ->fullWidth() + ->canSeeWhen('systemUser', $resource), + ]), + new Panel(__('Location'), [ + Select::make(__('Region'), 'region') + ->fullWidth() + ->displayUsingLabels() + ->searchable() + ->options(RegionRepo::values()) + ->default(RegionRepo::default()) + ->rules('required') + ->sortable(), + + BelongsTo::make(__('Branch'), 'branch', Branch::class), + ]), + new Panel(__('Personal data'), [ + Text::make(__('Passport name'), 'passport_name') + ->fullWidth() + ->rules('required', 'string', 'max:255'), + + Text::make(__('Passport surname'), 'passport_surname') + ->fullWidth() + ->rules('required', 'string', 'max:255'), + + NovaInputmask::make(__('Phone'), 'phone') + ->fullWidth() + ->phonenumber('TM') + ->rules('required', 'max:255') + ->hideFromIndex(), + + Text::make(__('Email'), 'email') + ->fullWidth() + ->rules('nullable', 'max:255', 'email') + ->hideFromIndex(), + + Text::make(__('Current Residence'), 'address') + ->fullWidth() + ->rules('required', 'string', 'max:255') + ->hideFromIndex(), + ]), + new Panel(__('Payment'), [ + SimpleRepeatable::make(__('Payment sender data'), 'sender_datas', [ + Select::make(__('Passport serie'), 'passport_serie') + ->displayUsingLabels() + ->searchable() + ->options(PassportRepo::values()) + ->rules('required') + ->sortable(), + + NovaInputmask::make(__('Passport number'), 'passport_number') + ->mask('999999') + ->rules('required', 'max:255'), + + Text::make( + name: sprintf('%s %s %s', __('Name'), __('Surname'), __('Patronic name')), + attribute: 'full_name' + ) + ->rules('required', 'max:255'), + ])->minRows(1)->rules('required'), + + SimpleRepeatable::make(__('Payee information'), 'payment_reciever', [ + Select::make(__('Passport serie'), 'passport_serie') + ->displayUsingLabels() + ->searchable() + ->options(PassportRepo::values()) + ->rules('required') + ->sortable(), + + NovaInputmask::make(__('Passport number'), 'passport_number') + ->mask('999999') + ->rules('required', 'max:255'), + + Text::make( + name: sprintf('%s %s %s', __('Name'), __('Surname'), __('Patronic name')), + attribute: 'full_name' + )->rules('required', 'max:255'), + ])->maxRows(1)->minRows(1)->rules('required'), + ]), + + new Panel(__('Reciver files'), TuitionPaymentOrderFileFields::reciverFiles()), + new Panel(__('Sender files'), TuitionPaymentOrderFileFields::senderFiles()), + ]; + } +} diff --git a/app/Modules/TuitionPaymentOrder/Nova/Resources/Concerns/TuitionPaymentOrderFieldsForIndex.php b/app/Modules/TuitionPaymentOrder/Nova/Resources/Concerns/TuitionPaymentOrderFieldsForIndex.php new file mode 100644 index 0000000..e7373e2 --- /dev/null +++ b/app/Modules/TuitionPaymentOrder/Nova/Resources/Concerns/TuitionPaymentOrderFieldsForIndex.php @@ -0,0 +1,58 @@ +hide(), + + Text::make(__('ID'), 'unique_id')->sortable(), + + DateTime::make(__('Created at'), 'created_at') + ->turkmenDateTime(), + + Select::make(__('Region'), 'region') + ->displayUsingLabels() + ->options(RegionRepo::values()) + ->canSeeWhen('isAdmin', $resource) + ->sortable(), + + BelongsTo::make(__('Branch'), 'branch', Branch::class) + ->canSeeWhen('isAdmin', $resource) + ->filterable() + ->sortable(), + + Text::make(__('Name'), 'passport_name'), + + Text::make(__('Surname'), 'passport_surname'), + + Text::make(__('Phone'), 'phone'), + + Badge::make(__('Status'), 'status') + ->map(OrderRepo::statusClasses()) + ->addTypes([ + 'primary' => 'dark:bg-gray-900 bg-gray-600 text-white', + ]) + ->labels(OrderRepo::statusValues()) + ->withIcons() + ->icons(OrderRepo::statusIcons()) + ->sortable(), + ]; + } +} diff --git a/app/Modules/TuitionPaymentOrder/Nova/Resources/NovaTuitionPaymentOrder.php b/app/Modules/TuitionPaymentOrder/Nova/Resources/NovaTuitionPaymentOrder.php new file mode 100644 index 0000000..6f5996c --- /dev/null +++ b/app/Modules/TuitionPaymentOrder/Nova/Resources/NovaTuitionPaymentOrder.php @@ -0,0 +1,247 @@ + + */ + public static $model = \App\Modules\TuitionPaymentOrder\Models\TuitionPaymentOrder::class; + + /** + * The single value that should be used to represent the resource when being displayed. + * + * @var string + */ + public static $title = 'unique_id'; + + /** + * The columns that should be searched. + * + * @var array + */ + public static $search = [ + 'unique_id', 'passport_name', 'passport_surname', 'phone', + ]; + + /** + * The relationships that should be eager loaded on index queries. + * + * @var array + */ + public static $with = ['branch']; + + /** + * Get the displayable label of the resource. + */ + public static function label(): string + { + return sprintf( + '%s (%s)', + __('Tuition payments'), + Str::lower(__('For students')) + ); + } + + /** + * Get the displayable singular label of the resource. + */ + public static function singularLabel(): string + { + return sprintf( + '%s (%s)', + __('Tuition payment'), + Str::lower(__('For students')) + ); + } + + /** + * After resource created + * + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Illuminate\Database\Eloquent\Model $model + */ + public static function afterCreate(NovaRequest $request, Model $model): void + { + $model->update(['unique_id' => CardOrderRepo::fillUniqueId($model)]); + } + + /** + * Get the fields for index. + */ + public function fieldsForIndex(): array + { + return TuitionPaymentOrderFieldsForIndex::make($this); + } + + /** + * Get the fields for detail + */ + public function fieldsForDetail(): array + { + return TuitionPaymentOrderFieldsForDetail::make($this); + } + + /** + * Get the fields displayed by the resource. + * + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @return array + */ + public function fields(NovaRequest $request): array + { + return [ + Tabs::make('Wizard', [ + new Tab(__('Status'), [ + ID::make() + ->hideFromDetail(), + + Hidden::make('user_id') + ->default(auth()->id()) + ->hideWhenUpdating(), + + Text::make(__('ID'), 'unique_id') + ->exceptOnForms(), + + Select::make(__('Status'), 'status') + ->displayUsingLabels() + ->searchable() + ->options(OrderRepo::statusValues()) + ->default(OrderRepo::defaultStatus()) + ->fullWidth() + ->hideFromDetail() + ->rules('required') + ->canSeeWhen('systemUser', $this), + + Badge::make(__('Status'), 'status') + ->map(OrderRepo::statusClasses()) + ->addTypes([ + 'primary' => 'dark:bg-gray-900 bg-gray-600 text-white', + ]) + ->labels(OrderRepo::statusValues()) + ->withIcons() + ->icons(OrderRepo::statusIcons()), + + Text::make(__('Note'), 'notes') + ->fullWidth() + ->canSeeWhen('systemUser', $this), + ]), + + new Tab(__('Location'), [ + Select::make(__('Region'), 'region') + ->fullWidth() + ->displayUsingLabels() + ->searchable() + ->options(RegionRepo::values()) + ->default(RegionRepo::default()) + ->rules('required') + ->sortable(), + + Select::make(__('Branch'), 'branch_id') + ->fullWidth() + ->displayUsingLabels() + ->searchable() + ->dependsOn('region', NovaRepo::dependsOnRegion('region', Branch::class)) + ->rules('required') + ->sortable(), + ]), + + new Tab(__('Personal data'), [ + Text::make(__('Passport name'), 'passport_name') + ->fullWidth() + ->rules('required', 'string', 'max:255'), + + Text::make(__('Passport surname'), 'passport_surname') + ->fullWidth() + ->rules('required', 'string', 'max:255'), + + NovaInputmask::make(__('Phone'), 'phone') + ->fullWidth() + ->phonenumber('TM') + ->rules('required', 'max:255') + ->hideFromIndex(), + + Text::make(__('Email'), 'email') + ->fullWidth() + ->rules('nullable', 'max:255', 'email') + ->hideFromIndex(), + + Text::make(__('Current Residence'), 'address') + ->fullWidth() + ->rules('required', 'string', 'max:255') + ->hideFromIndex(), + ]), + + new Tab(__('Payment'), [ + SimpleRepeatable::make(__('Payment sender data'), 'sender_datas', [ + Select::make(__('Passport serie'), 'passport_serie') + ->displayUsingLabels() + ->searchable() + ->options(PassportRepo::values()) + ->rules('required') + ->sortable(), + + NovaInputmask::make(__('Passport number'), 'passport_number') + ->mask('999999') + ->rules('required', 'max:255'), + + Text::make( + name: sprintf('%s %s %s', __('Name'), __('Surname'), __('Patronic name')), + attribute: 'full_name' + ) + ->rules('required', 'max:255'), + ])->minRows(1)->rules('required'), + + SimpleRepeatable::make(__('Payee information'), 'payment_reciever', [ + Select::make(__('Passport serie'), 'passport_serie') + ->displayUsingLabels() + ->searchable() + ->options(PassportRepo::values()) + ->rules('required') + ->sortable(), + + NovaInputmask::make(__('Passport number'), 'passport_number') + ->mask('999999') + ->rules('required', 'max:255'), + + Text::make( + name: sprintf('%s %s %s', __('Name'), __('Surname'), __('Patronic name')), + attribute: 'full_name' + )->rules('required', 'max:255'), + ])->maxRows(1)->minRows(1)->rules('required'), + ]), + + new Tab(__('Reciver files'), TuitionPaymentOrderFileFields::reciverFiles()), + new Tab(__('Sender files'), TuitionPaymentOrderFileFields::senderFiles()), + ], $request)->asWizard(), + ]; + } +} diff --git a/app/Modules/TuitionPaymentOrder/Nova/Resources/TuitionPaymentOrderFileFields.php b/app/Modules/TuitionPaymentOrder/Nova/Resources/TuitionPaymentOrderFileFields.php new file mode 100644 index 0000000..384967a --- /dev/null +++ b/app/Modules/TuitionPaymentOrder/Nova/Resources/TuitionPaymentOrderFileFields.php @@ -0,0 +1,63 @@ +map(function (array $file) { + return File::make(__($file['name']), $file['code']) + ->fullWidth() + ->deletable(false) + ->creationRules($file['required'] ? 'required' : 'nullable') + ->updateRules('nullable') + ->store(function (NovaRequest $request, $model) use ($file) { + return function () use ($model, $file) { + $model->addMediaFromRequest($file['code']) + ->preservingOriginal() + ->toMediaCollection($file['code']); + }; + }) + ->preview(function ($value, $disk, $resource) use ($file) { + return $resource->getFirstMediaUrl($file['code']); + }); + }) + ->toArray(); + } + + /** + * Sender files + */ + public static function senderFiles(): array + { + return collect(TuitionPaymentOrder::senderFiles()) + ->map(function (array $file) { + return File::make(__($file['name']), $file['code']) + ->fullWidth() + ->deletable(false) + ->creationRules($file['required'] ? 'required' : 'nullable') + ->updateRules('nullable') + ->store(function (NovaRequest $request, $model) use ($file) { + return function () use ($model, $file) { + $model->addMediaFromRequest($file['code']) + ->preservingOriginal() + ->toMediaCollection($file['code']); + }; + }) + ->preview(function ($value, $disk, $resource) use ($file) { + return $resource->getFirstMediaUrl($file['code']); + }); + }) + ->toArray(); + } +} diff --git a/app/Repos/System/Nova/NovaMenuRepo.php b/app/Repos/System/Nova/NovaMenuRepo.php index 9254947..0d8143e 100644 --- a/app/Repos/System/Nova/NovaMenuRepo.php +++ b/app/Repos/System/Nova/NovaMenuRepo.php @@ -3,6 +3,7 @@ namespace App\Repos\System\Nova; use App\Modules\SberPaymentOrder\Nova\Resources\NovaSberPaymentOrder; +use App\Modules\TuitionPaymentOrder\Nova\Resources\NovaTuitionPaymentOrder; use App\Modules\VisaMasterPaymentOrder\Nova\Resources\NovaVisaMasterPaymentOrder; use App\Nova\Dashboards\Main; use App\Nova\Resources\Branch\Branch; @@ -53,6 +54,7 @@ class NovaMenuRepo MenuGroup::make(__('International payments'), [ MenuItem::resource(NovaVisaMasterPaymentOrder::class), MenuItem::resource(NovaSberPaymentOrder::class), + MenuItem::resource(NovaTuitionPaymentOrder::class), ])->collapsedByDefault(), ])->icon('ticket')->collapsedByDefault(),