From 244fc1c15d725000a6bbf48994baffab38badcca Mon Sep 17 00:00:00 2001 From: Rahman Ramsi Date: Mon, 11 Dec 2023 16:08:51 +0800 Subject: [PATCH 1/9] disable sticky toolbar on tinyeditor --- app/Panel/Livewire/Submissions/CallforAbstract.php | 3 ++- app/Panel/Livewire/Submissions/Components/ParticipantList.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/Panel/Livewire/Submissions/CallforAbstract.php b/app/Panel/Livewire/Submissions/CallforAbstract.php index e88df541b..691649ee9 100644 --- a/app/Panel/Livewire/Submissions/CallforAbstract.php +++ b/app/Panel/Livewire/Submissions/CallforAbstract.php @@ -139,7 +139,8 @@ public function acceptAction() TextInput::make('subject') ->required(), TinyEditor::make('message') - ->minHeight(300), + ->minHeight(300) + ->toolbarSticky(false), Checkbox::make('no-notification') ->label("Don't send notification to author") ->default(false), diff --git a/app/Panel/Livewire/Submissions/Components/ParticipantList.php b/app/Panel/Livewire/Submissions/Components/ParticipantList.php index b499f4007..e29b14ec5 100644 --- a/app/Panel/Livewire/Submissions/Components/ParticipantList.php +++ b/app/Panel/Livewire/Submissions/Components/ParticipantList.php @@ -149,7 +149,8 @@ function (Model $record) { ->readOnly(), TinyEditor::make('message') ->minHeight(300) - ->columnSpanFull(), + ->columnSpanFull() + ->toolbarSticky(false), ]), Checkbox::make('no-notification') ->label("Don't Send Notification") From b4f5f13f81594b2d374154ede631b08030a6d78f Mon Sep 17 00:00:00 2001 From: Rahman Ramsi Date: Tue, 12 Dec 2023 11:55:47 +0800 Subject: [PATCH 2/9] add index --- .../migrations/2023_04_14_034800_create_submissions_table.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/database/migrations/2023_04_14_034800_create_submissions_table.php b/database/migrations/2023_04_14_034800_create_submissions_table.php index 54d69f859..bca2ebc40 100644 --- a/database/migrations/2023_04_14_034800_create_submissions_table.php +++ b/database/migrations/2023_04_14_034800_create_submissions_table.php @@ -26,6 +26,9 @@ public function up(): void $table->string('withdrawn_reason')->nullable(); $table->timestamp('withdrawn_at')->nullable(); $table->timestamps(); + + $table->index(['status']); + $table->index(['stage']); }); Schema::create('submission_meta', function (Blueprint $table) { From 82842c8f44b8670f199870f5a8de01b3ddcf9af0 Mon Sep 17 00:00:00 2001 From: Rahman Ramsi Date: Thu, 14 Dec 2023 11:01:14 +0800 Subject: [PATCH 3/9] wip --- app/Application.php | 2 + app/Facades/Payment.php | 14 ++ app/Interfaces/PaymentDriver.php | 22 +++ app/Managers/PaymentManager.php | 32 ++++ app/Models/Enums/PaymentState.php | 20 ++ app/Models/Enums/PaymentType.php | 14 ++ app/Models/Enums/SubmissionStage.php | 11 +- app/Models/Payment.php | 28 +++ app/Models/Submission.php | 6 +- app/Models/SubmissionPaymentItem.php | 34 ++++ app/Models/Timeline.php | 3 +- app/Observers/ConferenceObserver.php | 1 + app/Panel/Livewire/Submissions/Payment.php | 52 +++++ .../Workflows/Payment/Tables/PaymentItems.php | 137 +++++++++++++ .../Livewire/Workflows/PaymentSetting.php | 105 ++++++++++ app/Panel/Pages/Settings/Workflow.php | 23 ++- .../Pages/ViewSubmission.php | 37 ++-- app/Providers/Filament/PanelProvider.php | 2 +- app/Services/Payments/BasePayment.php | 11 ++ app/Services/Payments/ManualPayment.php | 68 +++++++ app/Tables/Columns/ListColumn.php | 10 + composer.json | 1 + composer.lock | 180 +++++++++++++++++- ...023_12_12_112200_create_payments_table.php | 61 ++++++ public/build/manifest.json | 6 +- .../livewire/submissions/editing.blade.php | 6 +- .../livewire/submissions/payment.blade.php | 8 + .../workflows/payment-setting.blade.php | 19 ++ .../payment/tables/payment-items.blade.php | 3 + resources/views/tables/columns/list.blade.php | 5 + 30 files changed, 889 insertions(+), 32 deletions(-) create mode 100644 app/Facades/Payment.php create mode 100644 app/Interfaces/PaymentDriver.php create mode 100644 app/Managers/PaymentManager.php create mode 100644 app/Models/Enums/PaymentState.php create mode 100644 app/Models/Enums/PaymentType.php create mode 100644 app/Models/Payment.php create mode 100644 app/Models/SubmissionPaymentItem.php create mode 100644 app/Panel/Livewire/Submissions/Payment.php create mode 100644 app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php create mode 100644 app/Panel/Livewire/Workflows/PaymentSetting.php create mode 100644 app/Services/Payments/BasePayment.php create mode 100644 app/Services/Payments/ManualPayment.php create mode 100644 app/Tables/Columns/ListColumn.php create mode 100644 database/migrations/2023_12_12_112200_create_payments_table.php create mode 100644 resources/views/panel/livewire/submissions/payment.blade.php create mode 100644 resources/views/panel/livewire/workflows/payment-setting.blade.php create mode 100644 resources/views/panel/livewire/workflows/payment/tables/payment-items.blade.php create mode 100644 resources/views/tables/columns/list.blade.php diff --git a/app/Application.php b/app/Application.php index 12ab7969a..0022c1b5d 100644 --- a/app/Application.php +++ b/app/Application.php @@ -12,6 +12,7 @@ use App\Models\Site; use App\Models\StaticPage; use App\Models\Submission; +use App\Models\SubmissionPaymentItem; use App\Models\Timeline; use App\Models\Topic; use App\Models\Venue; @@ -66,6 +67,7 @@ public function scopeCurrentConference(): void Announcement::class, StaticPage::class, Timeline::class, + SubmissionPaymentItem::class, ] as $model) { $model::addGlobalScope(new ConferenceScope); } diff --git a/app/Facades/Payment.php b/app/Facades/Payment.php new file mode 100644 index 000000000..ebb9d7e9e --- /dev/null +++ b/app/Facades/Payment.php @@ -0,0 +1,14 @@ +customCreators])->mapWithKeys(function ($driver) { + return [$driver => $this->driver($driver)->getName()]; + }); + } +} diff --git a/app/Models/Enums/PaymentState.php b/app/Models/Enums/PaymentState.php new file mode 100644 index 000000000..f6a5bf47b --- /dev/null +++ b/app/Models/Enums/PaymentState.php @@ -0,0 +1,20 @@ +name; + } +} diff --git a/app/Models/Enums/PaymentType.php b/app/Models/Enums/PaymentType.php new file mode 100644 index 000000000..bc7fa634b --- /dev/null +++ b/app/Models/Enums/PaymentType.php @@ -0,0 +1,14 @@ + PaymentState::Pending, + ]; + + /** + * The attributes that should be cast. + * + * @var array + */ + protected $casts = [ + 'state' => PaymentState::class, + ]; +} diff --git a/app/Models/Submission.php b/app/Models/Submission.php index 04785847b..b69636d3f 100644 --- a/app/Models/Submission.php +++ b/app/Models/Submission.php @@ -85,13 +85,13 @@ protected static function booted(): void static::created(function (Submission $submission) { $submission->participants()->create([ - 'user_id' => auth()->id(), + 'user_id' => $submission->user_id, 'role_id' => Role::where('name', UserRole::Author->value)->first()->getKey(), ]); //If current user does not exists in participant - if (! $userAsParticipant = auth()->user()->asParticipant()) { - $userAsParticipant = CreateParticipantFromUserAction::run(auth()->user()); + if (! $userAsParticipant = $submission->user->asParticipant()) { + $userAsParticipant = CreateParticipantFromUserAction::run($submission->user); } // Current user as a contributors diff --git a/app/Models/SubmissionPaymentItem.php b/app/Models/SubmissionPaymentItem.php new file mode 100644 index 000000000..581aa95db --- /dev/null +++ b/app/Models/SubmissionPaymentItem.php @@ -0,0 +1,34 @@ + + */ + protected $fillable = [ + 'name', + 'description', + 'fees', + ]; + + /** + * The attributes that should be cast. + * + * @var array + */ + protected $casts = [ + 'fees' => 'array', + ]; +} diff --git a/app/Models/Timeline.php b/app/Models/Timeline.php index 179acb6e2..8fe7b72af 100644 --- a/app/Models/Timeline.php +++ b/app/Models/Timeline.php @@ -3,12 +3,13 @@ namespace App\Models; use App\Models\Concerns\BelongsToConference; +use GeneaLabs\LaravelModelCaching\Traits\Cachable; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Timeline extends Model { - use BelongsToConference, HasFactory; + use Cachable, BelongsToConference, HasFactory; protected $fillable = [ 'title', diff --git a/app/Observers/ConferenceObserver.php b/app/Observers/ConferenceObserver.php index 60381e62c..e1abfb327 100644 --- a/app/Observers/ConferenceObserver.php +++ b/app/Observers/ConferenceObserver.php @@ -56,6 +56,7 @@ public function created(Conference $conference): void ]); $conference->setMeta('page_footer', view('examples.footer')->render()); + $conference->setMeta('workflow.payment.supported_currencies', ['USD']); $conference->save(); } diff --git a/app/Panel/Livewire/Submissions/Payment.php b/app/Panel/Livewire/Submissions/Payment.php new file mode 100644 index 000000000..8cbcbcb1b --- /dev/null +++ b/app/Panel/Livewire/Submissions/Payment.php @@ -0,0 +1,52 @@ + StageManager::peerReview()->isStageOpen(), + ]); + } + + public function form(Form $form) + { + // return PaymentFacade::getPaymentForm($form); + return $form->schema([ + + ]); + } +} diff --git a/app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php b/app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php new file mode 100644 index 000000000..a24ce7dd6 --- /dev/null +++ b/app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php @@ -0,0 +1,137 @@ +required(), + Textarea::make('description') + ->autosize(), + Repeater::make('fees') + ->required() + ->schema([ + Grid::make() + ->schema([ + Select::make('currency_id') + ->label('Currency') + ->searchable() + ->required() + ->disabled() + ->dehydrated(true) + // ->options(Currency::whereIn('id', App::getCurrentConference()->getMeta('workflow.payment.supported_currencies') ?? [])->pluck('name', 'id')) + ->options(Currency::pluck('name', 'id')) + ->optionsLimit(250) + ->distinct(), + TextInput::make('fee') + ->required() + ->minValue(1) + ->prefix(fn(Get $get) => $get('currency_id') ? Currency::find($get('currency_id'))->symbol_native : null) + ->numeric(), + ]), + ]) + ->deletable(false) + ->reorderable(false) + // ->reorderableWithButtons() + ->addable(false) + ->addActionLabel('Add Fee') + ]; + + return $table + ->query(SubmissionPaymentItem::query()) + ->reorderable('order_column') + ->heading('Payment Items') + ->paginated(false) + ->columns([ + IndexColumn::make('no'), + TextColumn::make('name') + ->searchable(), + TextColumn::make('description') + ->searchable() + ->wrap(), + ]) + ->headerActions([ + CreateAction::make() + ->label("New Payment Item") + ->mountUsing(function (Form $form) { + $fees = collect(App::getCurrentConference()->getMeta('workflow.payment.supported_currencies'))->map(function ($currency) { + return [ + 'currency_id' => $currency, + 'fee' => 0, + ]; + })->toArray(); + $form->fill([ + 'fees' => $fees + ]); + }) + ->model(SubmissionPaymentItem::class) + ->modalWidth('2xl') + ->form($formField) + ]) + ->filters([ + // ... + ]) + ->actions([ + EditAction::make() + ->mutateRecordDataUsing(function ($data) { + $supportedCurrencies = App::getCurrentConference()->getMeta('workflow.payment.supported_currencies') ?? []; + $fees = collect($supportedCurrencies) + ->map(fn ($currency) => ['currency_id' => $currency, 'fee' => 0]) + ->keyBy('currency_id') + ->merge(collect($data['fees'])->keyBy('currency_id')) + ->filter(fn($fee) => in_array($fee['currency_id'], $supportedCurrencies)) + ->toArray(); + $data['fees'] = $fees; + + return $data; + }) + ->modalWidth('2xl') + ->form($formField), + DeleteAction::make(), + ]) + ->bulkActions([ + // ... + ]); + } +} diff --git a/app/Panel/Livewire/Workflows/PaymentSetting.php b/app/Panel/Livewire/Workflows/PaymentSetting.php new file mode 100644 index 000000000..66d322adb --- /dev/null +++ b/app/Panel/Livewire/Workflows/PaymentSetting.php @@ -0,0 +1,105 @@ +form->fill([ + 'settings' => [ + 'payment_method' => $this->getSetting('payment_method', 'manual'), + 'supported_currencies' => $this->getSetting('supported_currencies'), + ], + ...Payment::getAllDriverNames()->map(fn ($name, $key) => Payment::driver($key)->getSettingFormFill())->toArray(), + ]); + } + + public function submitAction() + { + return Action::make('submitAction') + ->label('Save') + ->icon('lineawesome-save-solid') + ->failureNotificationTitle('Save Failed') + ->successNotificationTitle('Saved') + ->action(function (Action $action) { + $this->form->validate(); + + try { + $data = $this->form->getState(); + foreach ($data['settings'] as $key => $value) { + $this->updateSetting($key, $value); + } + + Payment::driver($data['settings']['payment_method']) + ->saveSetting(data_get($data, $data['settings']['payment_method'], [])); + } catch (\Throwable $th) { + //throw $th; + Log::error($th); + $action->failure(); + return; + } + + $action->success(); + }); + } + + public function form(Form $form): Form + { + return $form + ->statePath('data') + ->schema([ + Shout::make('stage-closed') + ->hidden(fn (): bool => $this->isStageOpen()) + ->color('warning') + ->content('The payment stage is not open yet, Start now or schedule opening'), + Select::make('settings.payment_method') + ->label('Payment Method') + ->required() + ->options(Payment::getAllDriverNames()) + ->reactive(), + Select::make('settings.supported_currencies') + ->searchable() + ->required() + ->multiple() + ->options(Currency::query()->get()->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name . ' (' . $currency->symbol_native . ')'])->toArray()) + ->optionsLimit(250), + Grid::make(1) + ->hidden(fn (Get $get) => !$get('settings.payment_method')) + ->schema(fn (Get $get) => Payment::driver($get('payment_method'))->getSettingFormSchema()) + ]); + } + + public function render() + { + return view('panel.livewire.workflows.payment-setting'); + } +} diff --git a/app/Panel/Pages/Settings/Workflow.php b/app/Panel/Pages/Settings/Workflow.php index e8d6a2626..e5825d6f0 100644 --- a/app/Panel/Pages/Settings/Workflow.php +++ b/app/Panel/Pages/Settings/Workflow.php @@ -7,6 +7,8 @@ use App\Infolists\Components\VerticalTabs\Tabs; use App\Panel\Livewire\Workflows\AbstractSetting; use App\Panel\Livewire\Workflows\EditingSetting; +use App\Panel\Livewire\Workflows\Payment\Tables\PaymentItems; +use App\Panel\Livewire\Workflows\PaymentSetting; use App\Panel\Livewire\Workflows\PeerReview\Forms\Guidelines; use App\Panel\Livewire\Workflows\PeerReviewSetting; use Filament\Facades\Filament; @@ -33,7 +35,7 @@ class Workflow extends Page implements HasForms, HasInfolists public function booted(): void { - abort_if(! static::canView(), 403); + abort_if(!static::canView(), 403); } public static function shouldRegisterNavigation(): bool @@ -50,6 +52,7 @@ public function infolist(Infolist $infolist): Infolist { return $infolist->schema([ Tabs::make() + ->persistTabInQueryString() ->tabs([ Tab::make('Call for Abstract') ->icon('iconpark-documentfolder-o') @@ -64,6 +67,24 @@ public function infolist(Infolist $infolist): Infolist ]), ]), ]), + Tab::make('Payment') + ->icon('heroicon-o-currency-dollar') + ->schema([ + HorizontalTabs::make() + ->tabs([ + HorizontalTab::make('General') + ->schema([ + LivewireEntry::make('payment-setting') + ->livewire(PaymentSetting::class), + ]), + HorizontalTab::make('Items') + ->schema([ + LivewireEntry::make('payment-items') + ->livewire(PaymentItems::class), + ]), + ]), + + ]), Tab::make('Peer Review') ->icon('iconpark-search-o') ->schema([ diff --git a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php index 41b53910f..d0cb8970e 100644 --- a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php +++ b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php @@ -21,6 +21,7 @@ use App\Panel\Livewire\Submissions\Forms\Detail; use App\Panel\Livewire\Submissions\Forms\Publish; use App\Panel\Livewire\Submissions\Forms\References; +use App\Panel\Livewire\Submissions\Payment; use App\Panel\Livewire\Submissions\PeerReview; use App\Panel\Livewire\Workflows\Classes\StageManager; use App\Panel\Livewire\Workflows\Concerns\InteractWithTenant; @@ -73,7 +74,7 @@ protected function getHeaderActions(): array $action->successRedirectUrl( static::getResource()::getUrl('view', [ 'record' => $this->record, - 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', + 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', ]) ); @@ -122,7 +123,7 @@ protected function getHeaderActions(): array $action->successRedirectUrl( SubmissionResource::getUrl('view', [ 'record' => $this->record, - 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', + 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', ]), ); $action->success(); @@ -133,7 +134,7 @@ protected function getHeaderActions(): array ->color('danger') ->extraAttributes(function (Action $action) { if (filled($this->record->withdrawn_reason)) { - $attributeValue = '$nextTick(() => { $wire.mountAction(\''.$action->getName().'\') })'; + $attributeValue = '$nextTick(() => { $wire.mountAction(\'' . $action->getName() . '\') })'; return [ 'x-init' => new HtmlString($attributeValue), @@ -157,7 +158,7 @@ protected function getHeaderActions(): array ]) ->requiresConfirmation() ->modalHeading(function () { - return $this->record->user->fullName.' has requested to withdraw this submission.'; + return $this->record->user->fullName . ' has requested to withdraw this submission.'; }) ->modalDescription("You can either reject the request or accept it, remember it can't be undone.") ->modalCancelActionLabel('Ignore') @@ -172,7 +173,7 @@ protected function getHeaderActions(): array $action->successRedirectUrl( SubmissionResource::getUrl('view', [ 'record' => $this->record, - 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', + 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', ]), ); $action->successNotificationTitle('Withdrawal request rejected'); @@ -192,7 +193,7 @@ protected function getHeaderActions(): array $action->successRedirectUrl( SubmissionResource::getUrl('view', [ 'record' => $this->record, - 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', + 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', ]), ); $action->success(); @@ -204,13 +205,13 @@ protected function getHeaderActions(): array public function getSubheading(): string|Htmlable|null { $badgeHtml = match ($this->record->status) { - SubmissionStatus::Queued => ''.SubmissionStatus::Queued->value.'', - SubmissionStatus::Declined => ''.SubmissionStatus::Declined->value.'', - SubmissionStatus::Withdrawn => ''.SubmissionStatus::Withdrawn->value.'', - SubmissionStatus::Published => ''.SubmissionStatus::Published->value.'', - SubmissionStatus::OnReview => ''.SubmissionStatus::OnReview->value.'', - SubmissionStatus::Incomplete => ''.SubmissionStatus::Incomplete->value.'', - SubmissionStatus::Editing => ''.SubmissionStatus::Editing->value.'', + SubmissionStatus::Queued => '' . SubmissionStatus::Queued->value . '', + SubmissionStatus::Declined => '' . SubmissionStatus::Declined->value . '', + SubmissionStatus::Withdrawn => '' . SubmissionStatus::Withdrawn->value . '', + SubmissionStatus::Published => '' . SubmissionStatus::Published->value . '', + SubmissionStatus::OnReview => '' . SubmissionStatus::OnReview->value . '', + SubmissionStatus::Incomplete => '' . SubmissionStatus::Incomplete->value . '', + SubmissionStatus::Editing => '' . SubmissionStatus::Editing->value . '', default => null, }; @@ -246,6 +247,14 @@ public function infolist(Infolist $infolist): Infolist 'submission' => $this->record, ]), ]), + Tab::make('Payment') + ->icon('heroicon-o-currency-dollar') + ->schema([ + LivewireEntry::make('payment') + ->livewire(Payment::class, [ + 'submission' => $this->record, + ]), + ]), Tab::make('Peer Review') ->visible( fn (): bool => StageManager::peerReview()->isStageOpen() @@ -298,7 +307,7 @@ public function infolist(Infolist $infolist): Infolist LivewireEntry::make('contributors') ->livewire(ContributorList::class, [ 'submission' => $this->record, - 'viewOnly' => ! auth()->user()->can('editing', $this->record), + 'viewOnly' => !auth()->user()->can('editing', $this->record), ]), ]), Tab::make('References') diff --git a/app/Providers/Filament/PanelProvider.php b/app/Providers/Filament/PanelProvider.php index d4a6755e1..e5c35eb13 100644 --- a/app/Providers/Filament/PanelProvider.php +++ b/app/Providers/Filament/PanelProvider.php @@ -232,7 +232,7 @@ public static function setupFilamentComponent() $tinyEditor ->setRelativeUrls(false) ->setRemoveScriptHost(false) - ->toolbarSticky(true); + ->toolbarSticky(false); }); } diff --git a/app/Services/Payments/BasePayment.php b/app/Services/Payments/BasePayment.php new file mode 100644 index 000000000..cf841796a --- /dev/null +++ b/app/Services/Payments/BasePayment.php @@ -0,0 +1,11 @@ +update([ + 'payment_amount' => $amount, + 'payment_status' => 'paid', + ]); + } + + public function getPaymentForm(Form $form): Form + { + return $form->schema([ + Section::make('Payment') + ->schema([ + TextInput::make('payment_amount') + ->label('Payment Amount') + ->placeholder('Payment Amount') + ->required() + ->rules('required', 'numeric'), + ]), + ]); + } + + public function getSettingFormSchema(): array + { + return [ + TinyEditor::make('manual.instructions') + ->label('Payment Instruction') + ->required(), + ]; + } + + public function getSettingFormFill(): array + { + $conference = App::getCurrentConference(); + + return [ + 'instructions' => $conference->getMeta('manual_payment.instructions'), + ]; + } + + public function saveSetting(array $data): void + { + $conference = App::getCurrentConference(); + + $conference->setManyMeta([ + 'manual_payment.instructions' => data_get($data, 'instructions'), + ]); + } +} diff --git a/app/Tables/Columns/ListColumn.php b/app/Tables/Columns/ListColumn.php new file mode 100644 index 000000000..739730409 --- /dev/null +++ b/app/Tables/Columns/ListColumn.php @@ -0,0 +1,10 @@ +id(); + $table->foreignIdFor(Conference::class)->constrained(); + $table->morphs('model'); + $table->enum('type', PaymentType::array()); + $table->enum('state', PaymentState::array())->default(PaymentState::Pending->value); + $table->double('amount'); + $table->string('currency_id'); + $table->timestamp('paid_at')->nullable(); + $table->string('payment_method'); + $table->timestamps(); + + $table->index(['type']); + $table->index(['state']); + }); + + Schema::create('submission_payment_items', function (Blueprint $table){ + $table->id(); + $table->foreignIdFor(Conference::class)->constrained(); + $table->string('name'); + $table->text('description')->nullable(); + $table->integer('order_column')->nullable(); + $table->json('fees'); + $table->boolean('active')->default(true); + $table->timestamps(); + }); + + // Schema::create('submission_payment_items_details', function (Blueprint $table){ + // $table->id(); + // $table->foreignId('submission_payment_item_id')->constrained('submission_payment_items', indexName:'items_details_item_id_foreign')->cascadeOnDelete(); + // $table->string('currency_id'); + // $table->double('fee'); + // $table->integer('order_column')->nullable(); + // $table->timestamps(); + // }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('payments'); + } +}; diff --git a/public/build/manifest.json b/public/build/manifest.json index e55fdd52c..f3e3596e9 100644 --- a/public/build/manifest.json +++ b/public/build/manifest.json @@ -4,7 +4,7 @@ "src": "resources/assets/images/logo.png" }, "resources/panel/css/panel.css": { - "file": "assets/panel-ddf5feee.css", + "file": "assets/panel-df6f1873.css", "isEntry": true, "src": "resources/panel/css/panel.css" }, @@ -14,12 +14,12 @@ "src": "resources/panel/js/panel.js" }, "resources/website/css/website.css": { - "file": "assets/website-c47d7688.css", + "file": "assets/website-163957e0.css", "isEntry": true, "src": "resources/website/css/website.css" }, "resources/website/js/website.js": { - "file": "assets/website-a9ec73b1.js", + "file": "assets/website-02a4b6a2.js", "isEntry": true, "src": "resources/website/js/website.js" } diff --git a/resources/views/panel/livewire/submissions/editing.blade.php b/resources/views/panel/livewire/submissions/editing.blade.php index 7205472a0..36d3d4ffc 100644 --- a/resources/views/panel/livewire/submissions/editing.blade.php +++ b/resources/views/panel/livewire/submissions/editing.blade.php @@ -11,12 +11,12 @@ {{-- Participants --}} @livewire(App\Panel\Livewire\Submissions\Components\ParticipantList::class, ['submission' => $submission, 'lazy' => true]) - + @can('publish', $submission) - + Publish @endcan - \ No newline at end of file + diff --git a/resources/views/panel/livewire/submissions/payment.blade.php b/resources/views/panel/livewire/submissions/payment.blade.php new file mode 100644 index 000000000..38a477472 --- /dev/null +++ b/resources/views/panel/livewire/submissions/payment.blade.php @@ -0,0 +1,8 @@ +@php + use App\Panel\Livewire\Submissions\Components; + use App\Models\Enums\SubmissionStage; + use App\Constants\SubmissionFileCategory; +@endphp +
+ {{ $this->form }} +
diff --git a/resources/views/panel/livewire/workflows/payment-setting.blade.php b/resources/views/panel/livewire/workflows/payment-setting.blade.php new file mode 100644 index 000000000..268bc8199 --- /dev/null +++ b/resources/views/panel/livewire/workflows/payment-setting.blade.php @@ -0,0 +1,19 @@ +
+
+
+

+ Payment +

+ @if ($this->isStageOpen()) + Open + @else + Close + @endif +
+ @livewire(App\Panel\Livewire\Workflows\Components\StageSchedule::class, ['stage' => $this->getStage()]) +
+
+ {{ $this->form }} + {{ $this->submitAction() }} +
+
diff --git a/resources/views/panel/livewire/workflows/payment/tables/payment-items.blade.php b/resources/views/panel/livewire/workflows/payment/tables/payment-items.blade.php new file mode 100644 index 000000000..0689aea9d --- /dev/null +++ b/resources/views/panel/livewire/workflows/payment/tables/payment-items.blade.php @@ -0,0 +1,3 @@ +
+ {{ $this->table }} +
\ No newline at end of file diff --git a/resources/views/tables/columns/list.blade.php b/resources/views/tables/columns/list.blade.php new file mode 100644 index 000000000..7ccc26ce3 --- /dev/null +++ b/resources/views/tables/columns/list.blade.php @@ -0,0 +1,5 @@ +
    + @foreach ($getState() as $item) +
  • {{ $item }}
  • + @endforeach +
From b84c18229926a6b059cfc18524c615ef63fed3e1 Mon Sep 17 00:00:00 2001 From: Rahman Ramsi Date: Fri, 15 Dec 2023 10:09:18 +0800 Subject: [PATCH 4/9] move method to state machine --- .../Submissions/UnpublishSubmissionAction.php | 22 -- app/Interfaces/PaymentDriver.php | 10 +- app/Models/Enums/PaymentState.php | 6 +- app/Models/Enums/PaymentType.php | 3 +- app/Models/Enums/SubmissionStage.php | 12 +- app/Models/Enums/SubmissionStatus.php | 16 +- app/Models/Payment.php | 1 - .../Interfaces/SubmissionStateInterface.php | 22 ++ .../States/Submission/BaseSubmissionState.php | 53 +++ .../Submission/DeclinedSubmissionState.php | 12 + .../Submission/EditingSubmissionState.php | 23 ++ .../Submission/IncompleteSubmissionState.php | 34 ++ .../Submission/OnReviewSubmissionState.php | 24 ++ .../Submission/PaymentSubmissionState.php | 23 ++ .../Submission/PublishedSubmissionState.php | 18 + .../Submission/QueuedSubmissionState.php | 30 ++ .../Submission/WithdrawnSubmissionState.php | 23 ++ app/Models/Submission.php | 24 ++ app/Models/SubmissionPaymentItem.php | 1 - app/Models/Timeline.php | 2 +- app/Observers/ConferenceObserver.php | 2 +- .../Livewire/Submissions/CallforAbstract.php | 79 ++--- .../Livewire/Submissions/Forms/Publish.php | 7 +- app/Panel/Livewire/Submissions/Payment.php | 20 +- app/Panel/Livewire/Submissions/PeerReview.php | 11 +- .../SubmissionWizard/Steps/ReviewStep.php | 27 +- .../Workflows/Classes/StageManager.php | 5 + .../Workflows/Payment/Tables/PaymentItems.php | 33 +- .../Livewire/Workflows/PaymentSetting.php | 16 +- app/Panel/Pages/Settings/Workflow.php | 2 +- app/Panel/Resources/SubmissionResource.php | 8 - .../Pages/ViewSubmission.php | 32 +- app/Services/Payments/BasePayment.php | 2 - app/Services/Payments/ManualPayment.php | 2 - ...023_12_12_112200_create_payments_table.php | 2 +- nohup.out | 313 ++++++++++++++++++ 36 files changed, 721 insertions(+), 199 deletions(-) delete mode 100644 app/Actions/Submissions/UnpublishSubmissionAction.php create mode 100644 app/Models/States/Interfaces/SubmissionStateInterface.php create mode 100644 app/Models/States/Submission/BaseSubmissionState.php create mode 100644 app/Models/States/Submission/DeclinedSubmissionState.php create mode 100644 app/Models/States/Submission/EditingSubmissionState.php create mode 100644 app/Models/States/Submission/IncompleteSubmissionState.php create mode 100644 app/Models/States/Submission/OnReviewSubmissionState.php create mode 100644 app/Models/States/Submission/PaymentSubmissionState.php create mode 100644 app/Models/States/Submission/PublishedSubmissionState.php create mode 100644 app/Models/States/Submission/QueuedSubmissionState.php create mode 100644 app/Models/States/Submission/WithdrawnSubmissionState.php create mode 100644 nohup.out diff --git a/app/Actions/Submissions/UnpublishSubmissionAction.php b/app/Actions/Submissions/UnpublishSubmissionAction.php deleted file mode 100644 index 9ae3f5cac..000000000 --- a/app/Actions/Submissions/UnpublishSubmissionAction.php +++ /dev/null @@ -1,22 +0,0 @@ - SubmissionStage::Editing, - 'status' => SubmissionStatus::Editing, - ], $submission); - } -} diff --git a/app/Interfaces/PaymentDriver.php b/app/Interfaces/PaymentDriver.php index 0c092c521..835d30838 100644 --- a/app/Interfaces/PaymentDriver.php +++ b/app/Interfaces/PaymentDriver.php @@ -6,17 +6,17 @@ interface PaymentDriver { - public function getName() : string; + public function getName(): string; public function pay($amount, $submission); - public function getPaymentForm(Form $form) : Form; + public function getPaymentForm(Form $form): Form; + + public function getSettingFormSchema(): array; - public function getSettingFormSchema() : array; - public function getSettingFormFill(): array; public function saveSetting(array $data): void; // public function fillSettingForm(Form $form): void; -} \ No newline at end of file +} diff --git a/app/Models/Enums/PaymentState.php b/app/Models/Enums/PaymentState.php index f6a5bf47b..9d89eec6a 100644 --- a/app/Models/Enums/PaymentState.php +++ b/app/Models/Enums/PaymentState.php @@ -9,9 +9,9 @@ enum PaymentState: string implements HasLabel { use UsefulEnums; - case Pending = 'Pending'; - case Confirmation = 'Confirmation'; - case Paid = 'Paid'; + case Pending = 'Pending'; + case Confirmation = 'Confirmation'; + case Paid = 'Paid'; public function getLabel(): ?string { diff --git a/app/Models/Enums/PaymentType.php b/app/Models/Enums/PaymentType.php index bc7fa634b..3daaff98c 100644 --- a/app/Models/Enums/PaymentType.php +++ b/app/Models/Enums/PaymentType.php @@ -3,9 +3,8 @@ namespace App\Models\Enums; use App\Models\Enums\Concern\UsefulEnums; -use Filament\Support\Contracts\HasLabel; -enum PaymentType: string +enum PaymentType: string { use UsefulEnums; diff --git a/app/Models/Enums/SubmissionStage.php b/app/Models/Enums/SubmissionStage.php index 52e4c6db5..46d7d15ec 100644 --- a/app/Models/Enums/SubmissionStage.php +++ b/app/Models/Enums/SubmissionStage.php @@ -9,12 +9,12 @@ enum SubmissionStage: string implements HasLabel { use UsefulEnums; - case Wizard = 'Wizard'; - case CallforAbstract = 'Call for Abstract'; - case Payment = 'Payment'; - case PeerReview = 'Peer Review'; - case Editing = 'Editing'; - case Proceeding = 'Proceeding'; + case Wizard = 'Wizard'; + case CallforAbstract = 'Call for Abstract'; + case Payment = 'Payment'; + case PeerReview = 'Peer Review'; + case Editing = 'Editing'; + case Proceeding = 'Proceeding'; public function getLabel(): ?string { diff --git a/app/Models/Enums/SubmissionStatus.php b/app/Models/Enums/SubmissionStatus.php index 656525bdc..186723cfd 100644 --- a/app/Models/Enums/SubmissionStatus.php +++ b/app/Models/Enums/SubmissionStatus.php @@ -3,14 +3,16 @@ namespace App\Models\Enums; use App\Models\Enums\Concern\UsefulEnums; +use Filament\Support\Contracts\HasColor; use Filament\Support\Contracts\HasLabel; -enum SubmissionStatus: string implements HasLabel +enum SubmissionStatus: string implements HasLabel, HasColor { use UsefulEnums; case Incomplete = 'Incomplete'; case Queued = 'Queued'; + case Payment = 'Payment'; case OnReview = 'On Review'; case Editing = 'Editing'; case Published = 'Published'; @@ -22,4 +24,16 @@ public function getLabel(): ?string { return $this->name; } + + public function getColor(): string | array | null + { + return match ($this) { + self::Declined, self::Withdrawn => 'danger', + self::OnReview => 'warning', + self::Queued, self::Payment => 'primary', + self::Editing => 'info', + self::Published => 'success', + default => 'gray' + }; + } } diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 72caba686..8d4455734 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -3,7 +3,6 @@ namespace App\Models; use App\Models\Enums\PaymentState; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Payment extends Model diff --git a/app/Models/States/Interfaces/SubmissionStateInterface.php b/app/Models/States/Interfaces/SubmissionStateInterface.php new file mode 100644 index 000000000..c9ba00b97 --- /dev/null +++ b/app/Models/States/Interfaces/SubmissionStateInterface.php @@ -0,0 +1,22 @@ + SubmissionStage::Proceeding, + 'status' => SubmissionStatus::Published, + ], $this->submission); + } + + public function withdraw(): void + { + SubmissionUpdateAction::run(['status' => SubmissionStatus::Withdrawn], $this->submission); + } +} diff --git a/app/Models/States/Submission/IncompleteSubmissionState.php b/app/Models/States/Submission/IncompleteSubmissionState.php new file mode 100644 index 000000000..3cfbb2415 --- /dev/null +++ b/app/Models/States/Submission/IncompleteSubmissionState.php @@ -0,0 +1,34 @@ + SubmissionStage::CallforAbstract, + 'status' => SubmissionStatus::Queued, + ], $this->submission); + + Mail::to($this->submission->user)->send( + new ThankAuthorMail($this->submission) + ); + + User::role([ + UserRole::Admin->value, + UserRole::ConferenceManager->value, + ]) + ->lazy() + ->each(fn ($user) => $user->notify(new NewSubmission($this->submission))); + } +} diff --git a/app/Models/States/Submission/OnReviewSubmissionState.php b/app/Models/States/Submission/OnReviewSubmissionState.php new file mode 100644 index 000000000..5f5b7a11f --- /dev/null +++ b/app/Models/States/Submission/OnReviewSubmissionState.php @@ -0,0 +1,24 @@ + false, + 'stage' => SubmissionStage::Editing, + 'status' => SubmissionStatus::Editing, + ], $this->submission); + } + + public function withdraw(): void + { + SubmissionUpdateAction::run(['status' => SubmissionStatus::Withdrawn], $this->submission); + } +} diff --git a/app/Models/States/Submission/PaymentSubmissionState.php b/app/Models/States/Submission/PaymentSubmissionState.php new file mode 100644 index 000000000..7630d541c --- /dev/null +++ b/app/Models/States/Submission/PaymentSubmissionState.php @@ -0,0 +1,23 @@ + SubmissionStage::PeerReview, + 'status' => SubmissionStatus::OnReview, + ], $this->submission); + } + + public function withdraw(): void + { + SubmissionUpdateAction::run(['status' => SubmissionStatus::Withdrawn], $this->submission); + } +} diff --git a/app/Models/States/Submission/PublishedSubmissionState.php b/app/Models/States/Submission/PublishedSubmissionState.php new file mode 100644 index 000000000..e152f7aa9 --- /dev/null +++ b/app/Models/States/Submission/PublishedSubmissionState.php @@ -0,0 +1,18 @@ + SubmissionStage::Editing, + 'status' => SubmissionStatus::Editing, + ], $this->submission); + } +} diff --git a/app/Models/States/Submission/QueuedSubmissionState.php b/app/Models/States/Submission/QueuedSubmissionState.php new file mode 100644 index 000000000..a12d6111b --- /dev/null +++ b/app/Models/States/Submission/QueuedSubmissionState.php @@ -0,0 +1,30 @@ + SubmissionStage::Payment, + 'status' => SubmissionStatus::Payment, + ], $this->submission); + } + + public function decline():void + { + SubmissionUpdateAction::run([ + 'status' => SubmissionStatus::Declined, + ], $this->submission); + } + + public function withdraw(): void + { + SubmissionUpdateAction::run(['status' => SubmissionStatus::Withdrawn], $this->submission); + } +} diff --git a/app/Models/States/Submission/WithdrawnSubmissionState.php b/app/Models/States/Submission/WithdrawnSubmissionState.php new file mode 100644 index 000000000..35d0c48b6 --- /dev/null +++ b/app/Models/States/Submission/WithdrawnSubmissionState.php @@ -0,0 +1,23 @@ + SubmissionStage::Proceeding, + 'status' => SubmissionStatus::Published, + ], $this->submission); + } + + public function withdraw(): void + { + SubmissionUpdateAction::run(['status' => SubmissionStatus::Withdrawn], $this->submission); + } +} diff --git a/app/Models/Submission.php b/app/Models/Submission.php index b69636d3f..679f66a12 100644 --- a/app/Models/Submission.php +++ b/app/Models/Submission.php @@ -8,6 +8,15 @@ use App\Models\Enums\SubmissionStatus; use App\Models\Enums\UserRole; use App\Models\Meta\SubmissionMeta; +use App\Models\States\Submission\BaseSubmissionState; +use App\Models\States\Submission\DeclinedSubmissionState; +use App\Models\States\Submission\EditingSubmissionState; +use App\Models\States\Submission\IncompleteSubmissionState; +use App\Models\States\Submission\OnReviewSubmissionState; +use App\Models\States\Submission\PaymentSubmissionState; +use App\Models\States\Submission\PublishedSubmissionState; +use App\Models\States\Submission\QueuedSubmissionState; +use App\Models\States\Submission\WithdrawnSubmissionState; use GeneaLabs\LaravelModelCaching\Traits\Cachable; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -175,4 +184,19 @@ public function getEditors(): Collection ->pluck('user_id') ->map(fn ($userId) => User::find($userId)); } + + public function state(): BaseSubmissionState + { + return match ($this->status) { + SubmissionStatus::Incomplete => new IncompleteSubmissionState($this), + SubmissionStatus::Queued => new QueuedSubmissionState($this), + SubmissionStatus::Payment => new PaymentSubmissionState($this), + SubmissionStatus::OnReview => new OnReviewSubmissionState($this), + SubmissionStatus::Editing => new EditingSubmissionState($this), + SubmissionStatus::Published => new PublishedSubmissionState($this), + SubmissionStatus::Declined => new DeclinedSubmissionState($this), + SubmissionStatus::Withdrawn => new WithdrawnSubmissionState($this), + default => throw new \Exception('Invalid submission status'), + }; + } } diff --git a/app/Models/SubmissionPaymentItem.php b/app/Models/SubmissionPaymentItem.php index 581aa95db..5e2e65e17 100644 --- a/app/Models/SubmissionPaymentItem.php +++ b/app/Models/SubmissionPaymentItem.php @@ -3,7 +3,6 @@ namespace App\Models; use App\Models\Concerns\BelongsToConference; -use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Spatie\EloquentSortable\Sortable; use Spatie\EloquentSortable\SortableTrait; diff --git a/app/Models/Timeline.php b/app/Models/Timeline.php index 8fe7b72af..2faceae1c 100644 --- a/app/Models/Timeline.php +++ b/app/Models/Timeline.php @@ -9,7 +9,7 @@ class Timeline extends Model { - use Cachable, BelongsToConference, HasFactory; + use BelongsToConference, Cachable, HasFactory; protected $fillable = [ 'title', diff --git a/app/Observers/ConferenceObserver.php b/app/Observers/ConferenceObserver.php index e1abfb327..1191b38ff 100644 --- a/app/Observers/ConferenceObserver.php +++ b/app/Observers/ConferenceObserver.php @@ -56,7 +56,7 @@ public function created(Conference $conference): void ]); $conference->setMeta('page_footer', view('examples.footer')->render()); - $conference->setMeta('workflow.payment.supported_currencies', ['USD']); + $conference->setMeta('workflow.payment.supported_currencies', ['USD']); $conference->save(); } diff --git a/app/Panel/Livewire/Submissions/CallforAbstract.php b/app/Panel/Livewire/Submissions/CallforAbstract.php index 691649ee9..70f01daf0 100644 --- a/app/Panel/Livewire/Submissions/CallforAbstract.php +++ b/app/Panel/Livewire/Submissions/CallforAbstract.php @@ -23,6 +23,7 @@ use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; +use Illuminate\Support\Facades\Log; use Livewire\Component; use Mohamedsabil83\FilamentFormsTinyeditor\Components\TinyEditor; @@ -69,10 +70,7 @@ public function declineAction() ->successNotificationTitle('Submission declined') ->successRedirectUrl(fn (): string => SubmissionResource::getUrl('view', ['record' => $this->submission])) ->action(function (Action $action, array $data) { - SubmissionUpdateAction::run([ - 'stage' => SubmissionStage::CallforAbstract, - 'status' => SubmissionStatus::Declined, - ], $this->submission); + $this->submission->state()->decline(); if (! $data['no-notification']) { try { @@ -148,46 +146,49 @@ public function acceptAction() ]) ->action( function (Action $action, array $data) { - SubmissionUpdateAction::run([ - 'stage' => SubmissionStage::PeerReview, - 'status' => SubmissionStatus::OnReview, - ], $this->submission); + try { + $this->submission->state()->acceptAbstract(); - if (! $data['no-notification']) { - try { - $this->submission->user - ->notify( - new AbstractAccepted( - submission: $this->submission, - message: $data['message'], - subject: $data['subject'], - channels: ['mail'] - ) - ); - } catch (\Exception $e) { - $action->failureNotificationTitle('The email notification was not delivered.'); - $action->failure(); + if (! $data['no-notification']) { + try { + $this->submission->user + ->notify( + new AbstractAccepted( + submission: $this->submission, + message: $data['message'], + subject: $data['subject'], + channels: ['mail'] + ) + ); + } catch (\Exception $e) { + $action->failureNotificationTitle('The email notification was not delivered.'); + $action->failure(); + } } - } - $this->submission->user - ->notify( - new AbstractAccepted( - submission: $this->submission, - message: $data['message'], - subject: $data['subject'], - channels: ['database'] - ) - ); + $this->submission->user + ->notify( + new AbstractAccepted( + submission: $this->submission, + message: $data['message'], + subject: $data['subject'], + channels: ['database'] + ) + ); - $action->successRedirectUrl( - SubmissionResource::getUrl('view', [ - 'record' => $this->submission->getKey(), - 'stage' => '-peer-review-tab', - ]) - ); + $action->successRedirectUrl( + SubmissionResource::getUrl('view', [ + 'record' => $this->submission->getKey(), + 'stage' => '-payment-tab', + ]) + ); - $action->success(); + $action->success(); + } catch (\Throwable $th) { + Log::error($th->getMessage()); + $action->failureNotificationTitle('Failed to accept abstract'); + $action->failure(); + } } ); } diff --git a/app/Panel/Livewire/Submissions/Forms/Publish.php b/app/Panel/Livewire/Submissions/Forms/Publish.php index 04872d73d..502d3d187 100644 --- a/app/Panel/Livewire/Submissions/Forms/Publish.php +++ b/app/Panel/Livewire/Submissions/Forms/Publish.php @@ -34,11 +34,8 @@ class Publish extends \Livewire\Component implements HasActions, HasForms, HasIn public Submission $submission; public function handlePublishAction(Action $action, array $data) - { - SubmissionUpdateAction::run([ - 'stage' => SubmissionStage::Proceeding, - 'status' => SubmissionStatus::Published, - ], $this->submission); + { + $this->submission->state()->publish(); if (! $data['do-not-notify-author']) { try { diff --git a/app/Panel/Livewire/Submissions/Payment.php b/app/Panel/Livewire/Submissions/Payment.php index 8cbcbcb1b..a178d9a72 100644 --- a/app/Panel/Livewire/Submissions/Payment.php +++ b/app/Panel/Livewire/Submissions/Payment.php @@ -2,32 +2,16 @@ namespace App\Panel\Livewire\Submissions; -use App\Actions\Submissions\SubmissionUpdateAction; -use App\Mail\Templates\AcceptAbstractMail; -use App\Mail\Templates\DeclineAbstractMail; -use App\Managers\PaymentManager; -use App\Models\Enums\SubmissionStage; -use App\Models\Enums\SubmissionStatus; -use App\Models\MailTemplate; +use App\Facades\Payment as PaymentFacade; use App\Models\Submission; -use App\Notifications\AbstractAccepted; -use App\Notifications\AbstractDeclined; use App\Panel\Livewire\Workflows\Classes\StageManager; use App\Panel\Livewire\Workflows\Concerns\InteractWithTenant; -use App\Panel\Resources\SubmissionResource; -use Filament\Actions\Action; use Filament\Actions\Concerns\InteractsWithActions; use Filament\Actions\Contracts\HasActions; -use Filament\Forms\Components\Checkbox; -use Filament\Forms\Components\Fieldset; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\TextInput; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; use Livewire\Component; -use Mohamedsabil83\FilamentFormsTinyeditor\Components\TinyEditor; -use App\Facades\Payment as PaymentFacade; class Payment extends Component implements HasActions, HasForms { @@ -46,7 +30,7 @@ public function form(Form $form) { // return PaymentFacade::getPaymentForm($form); return $form->schema([ - + ]); } } diff --git a/app/Panel/Livewire/Submissions/PeerReview.php b/app/Panel/Livewire/Submissions/PeerReview.php index 45731eebf..128374b49 100644 --- a/app/Panel/Livewire/Submissions/PeerReview.php +++ b/app/Panel/Livewire/Submissions/PeerReview.php @@ -74,10 +74,7 @@ public function declineSubmissionAction() ]), ]) ->action(function (Action $action, array $data) { - SubmissionUpdateAction::run([ - 'revision_required' => false, - 'status' => SubmissionStatus::Declined, - ], $this->submission); + $this->submission->state()->decline(); if (! $data['do-not-notify-author']) { try { @@ -138,11 +135,7 @@ public function acceptSubmissionAction() ]), ]) ->action(function (Action $action, array $data) { - SubmissionUpdateAction::run([ - 'revision_required' => false, - 'stage' => SubmissionStage::Editing, - 'status' => SubmissionStatus::Editing, - ], $this->submission); + $this->submission->state()->accept(); if (! $data['do-not-notify-author']) { try { diff --git a/app/Panel/Livewire/Wizards/SubmissionWizard/Steps/ReviewStep.php b/app/Panel/Livewire/Wizards/SubmissionWizard/Steps/ReviewStep.php index 076b121e6..d34c4caa8 100644 --- a/app/Panel/Livewire/Wizards/SubmissionWizard/Steps/ReviewStep.php +++ b/app/Panel/Livewire/Wizards/SubmissionWizard/Steps/ReviewStep.php @@ -2,14 +2,7 @@ namespace App\Panel\Livewire\Wizards\SubmissionWizard\Steps; -use App\Actions\Submissions\SubmissionUpdateAction; -use App\Mail\Templates\ThankAuthorMail; -use App\Models\Enums\SubmissionStage; -use App\Models\Enums\SubmissionStatus; -use App\Models\Enums\UserRole; use App\Models\Submission; -use App\Models\User; -use App\Notifications\NewSubmission; use App\Panel\Livewire\Wizards\SubmissionWizard\Contracts\HasWizardStep; use App\Panel\Resources\SubmissionResource; use Filament\Actions\Action; @@ -17,7 +10,6 @@ use Filament\Actions\Contracts\HasActions; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; -use Illuminate\Support\Facades\Mail; use Livewire\Component; class ReviewStep extends Component implements HasActions, HasForms, HasWizardStep @@ -42,29 +34,14 @@ public function submitAction() ->requiresConfirmation() ->modalHeading('Submit abstract') ->modalDescription(function (): string { - return 'Your about to submit your abstract to the conference, Please review your submission carefully before proceeding.'; + return 'You will be submitting your abstract to the conference, Please review your submission carefully before proceeding.'; }) ->modalSubmitActionLabel('Submit') ->successNotificationTitle('Abstract submitted, please wait for the conference manager to review your submission.') ->successRedirectUrl(fn (): string => SubmissionResource::getUrl('complete', ['record' => $this->record])) ->action(function (Action $action) { - - SubmissionUpdateAction::run([ - 'stage' => SubmissionStage::CallforAbstract, - 'status' => SubmissionStatus::Queued, - ], $this->record); - try { - Mail::to($this->record->user)->send( - new ThankAuthorMail($this->record) - ); - - $users = User::role([ - UserRole::Admin->value, - UserRole::ConferenceManager->value, - ])->get(); - - $users->each(fn ($user) => $user->notify(new NewSubmission($this->record))); + $this->record->state()->fulfill(); } catch (\Exception $e) { $action->failureNotificationTitle('Failed to send notifications'); $action->failure(); diff --git a/app/Panel/Livewire/Workflows/Classes/StageManager.php b/app/Panel/Livewire/Workflows/Classes/StageManager.php index efe8469cf..d48ebb313 100644 --- a/app/Panel/Livewire/Workflows/Classes/StageManager.php +++ b/app/Panel/Livewire/Workflows/Classes/StageManager.php @@ -22,6 +22,11 @@ public static function callForAbstract(): static return static::stage('call-for-abstract'); } + public static function payment(): static + { + return static::stage('payment'); + } + public static function peerReview(): static { return static::stage('peer-review'); diff --git a/app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php b/app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php index a24ce7dd6..7259c4f60 100644 --- a/app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php +++ b/app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php @@ -3,39 +3,30 @@ namespace App\Panel\Livewire\Workflows\Payment\Tables; use App\Models\SubmissionPaymentItem; -use Filament\Forms\Form; -use Filament\Forms\Contracts\HasForms; -use Stevebauman\Purify\Facades\Purify; -use Filament\Tables\Contracts\HasTable; -use Filament\Notifications\Notification; -use Filament\Forms\Concerns\InteractsWithForms; -use Filament\Tables\Concerns\InteractsWithTable; -use App\Panel\Livewire\Workflows\Concerns\InteractWithTenant; use App\Tables\Columns\IndexColumn; -use App\Tables\Columns\ListColumn; -use Faker\Provider\ar_EG\Text; use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Group; use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; +use Filament\Forms\Concerns\InteractsWithForms; +use Filament\Forms\Contracts\HasForms; +use Filament\Forms\Form; use Filament\Forms\Get; use Filament\Tables\Actions\CreateAction; use Filament\Tables\Actions\DeleteAction; use Filament\Tables\Actions\EditAction; -use Filament\Tables\Columns\Layout\Panel; -use Filament\Tables\Columns\Layout\Stack; use Filament\Tables\Columns\TextColumn; +use Filament\Tables\Concerns\InteractsWithTable; +use Filament\Tables\Contracts\HasTable; use Filament\Tables\Table; use Illuminate\Support\Facades\App; -use Mohamedsabil83\FilamentFormsTinyeditor\Components\TinyEditor; use Squire\Models\Currency; class PaymentItems extends \Livewire\Component implements HasForms, HasTable { - use InteractsWithTable; use InteractsWithForms; + use InteractsWithTable; public function render() { @@ -67,7 +58,7 @@ public function table(Table $table): Table TextInput::make('fee') ->required() ->minValue(1) - ->prefix(fn(Get $get) => $get('currency_id') ? Currency::find($get('currency_id'))->symbol_native : null) + ->prefix(fn (Get $get) => $get('currency_id') ? Currency::find($get('currency_id'))->symbol_native : null) ->numeric(), ]), ]) @@ -75,7 +66,7 @@ public function table(Table $table): Table ->reorderable(false) // ->reorderableWithButtons() ->addable(false) - ->addActionLabel('Add Fee') + ->addActionLabel('Add Fee'), ]; return $table @@ -93,7 +84,7 @@ public function table(Table $table): Table ]) ->headerActions([ CreateAction::make() - ->label("New Payment Item") + ->label('New Payment Item') ->mountUsing(function (Form $form) { $fees = collect(App::getCurrentConference()->getMeta('workflow.payment.supported_currencies'))->map(function ($currency) { return [ @@ -102,12 +93,12 @@ public function table(Table $table): Table ]; })->toArray(); $form->fill([ - 'fees' => $fees + 'fees' => $fees, ]); }) ->model(SubmissionPaymentItem::class) ->modalWidth('2xl') - ->form($formField) + ->form($formField), ]) ->filters([ // ... @@ -120,7 +111,7 @@ public function table(Table $table): Table ->map(fn ($currency) => ['currency_id' => $currency, 'fee' => 0]) ->keyBy('currency_id') ->merge(collect($data['fees'])->keyBy('currency_id')) - ->filter(fn($fee) => in_array($fee['currency_id'], $supportedCurrencies)) + ->filter(fn ($fee) => in_array($fee['currency_id'], $supportedCurrencies)) ->toArray(); $data['fees'] = $fees; diff --git a/app/Panel/Livewire/Workflows/PaymentSetting.php b/app/Panel/Livewire/Workflows/PaymentSetting.php index 66d322adb..c3139eb08 100644 --- a/app/Panel/Livewire/Workflows/PaymentSetting.php +++ b/app/Panel/Livewire/Workflows/PaymentSetting.php @@ -3,23 +3,18 @@ namespace App\Panel\Livewire\Workflows; use App\Facades\Payment; -use App\Panel\Livewire\Submissions\Components\Files\SubmissionFilesTable; use App\Panel\Livewire\Workflows\Base\WorkflowStage; use Awcodes\Shout\Components\Shout; use Filament\Actions\Action; use Filament\Actions\Concerns\InteractsWithActions; use Filament\Actions\Contracts\HasActions; use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Section; use Filament\Forms\Components\Select; -use Filament\Forms\Components\TagsInput; -use Filament\Forms\Components\Textarea; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; use Filament\Forms\Get; use Illuminate\Support\Facades\Log; -use Mohamedsabil83\FilamentFormsTinyeditor\Components\TinyEditor; use Squire\Models\Currency; class PaymentSetting extends WorkflowStage implements HasActions, HasForms @@ -36,7 +31,7 @@ public function mount() { $this->form->fill([ 'settings' => [ - 'payment_method' => $this->getSetting('payment_method', 'manual'), + 'payment_method' => $this->getSetting('payment_method', 'manual'), 'supported_currencies' => $this->getSetting('supported_currencies'), ], ...Payment::getAllDriverNames()->map(fn ($name, $key) => Payment::driver($key)->getSettingFormFill())->toArray(), @@ -58,13 +53,14 @@ public function submitAction() foreach ($data['settings'] as $key => $value) { $this->updateSetting($key, $value); } - + Payment::driver($data['settings']['payment_method']) ->saveSetting(data_get($data, $data['settings']['payment_method'], [])); } catch (\Throwable $th) { //throw $th; Log::error($th); $action->failure(); + return; } @@ -90,11 +86,11 @@ public function form(Form $form): Form ->searchable() ->required() ->multiple() - ->options(Currency::query()->get()->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name . ' (' . $currency->symbol_native . ')'])->toArray()) + ->options(Currency::query()->get()->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name.' ('.$currency->symbol_native.')'])->toArray()) ->optionsLimit(250), Grid::make(1) - ->hidden(fn (Get $get) => !$get('settings.payment_method')) - ->schema(fn (Get $get) => Payment::driver($get('payment_method'))->getSettingFormSchema()) + ->hidden(fn (Get $get) => ! $get('settings.payment_method')) + ->schema(fn (Get $get) => Payment::driver($get('payment_method'))->getSettingFormSchema()), ]); } diff --git a/app/Panel/Pages/Settings/Workflow.php b/app/Panel/Pages/Settings/Workflow.php index e5825d6f0..2b0b466d5 100644 --- a/app/Panel/Pages/Settings/Workflow.php +++ b/app/Panel/Pages/Settings/Workflow.php @@ -35,7 +35,7 @@ class Workflow extends Page implements HasForms, HasInfolists public function booted(): void { - abort_if(!static::canView(), 403); + abort_if(! static::canView(), 403); } public static function shouldRegisterNavigation(): bool diff --git a/app/Panel/Resources/SubmissionResource.php b/app/Panel/Resources/SubmissionResource.php index d581d5550..9e72eacdd 100644 --- a/app/Panel/Resources/SubmissionResource.php +++ b/app/Panel/Resources/SubmissionResource.php @@ -137,14 +137,6 @@ public static function table(Table $table): Table 'class' => 'mt-2', ]) ->badge() - ->color(fn (Submission $record): string => match ($record->status) { - SubmissionStatus::Declined, SubmissionStatus::Withdrawn => 'danger', - SubmissionStatus::OnReview => 'warning', - SubmissionStatus::Queued => 'primary', - SubmissionStatus::Editing => 'info', - SubmissionStatus::Published => 'success', - default => 'gray' - }) ->formatStateUsing( fn (Submission $record) => $record->status ), diff --git a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php index d0cb8970e..b4f4b98e8 100644 --- a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php +++ b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php @@ -70,11 +70,12 @@ protected function getHeaderActions(): array ->requiresConfirmation() ->successNotificationTitle('Submission unpublished') ->action(function (Action $action) { - UnpublishSubmissionAction::run($this->record); + $this->record->state()->unpublish(); + $action->successRedirectUrl( static::getResource()::getUrl('view', [ 'record' => $this->record, - 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', + 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', ]) ); @@ -123,7 +124,7 @@ protected function getHeaderActions(): array $action->successRedirectUrl( SubmissionResource::getUrl('view', [ 'record' => $this->record, - 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', + 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', ]), ); $action->success(); @@ -134,7 +135,7 @@ protected function getHeaderActions(): array ->color('danger') ->extraAttributes(function (Action $action) { if (filled($this->record->withdrawn_reason)) { - $attributeValue = '$nextTick(() => { $wire.mountAction(\'' . $action->getName() . '\') })'; + $attributeValue = '$nextTick(() => { $wire.mountAction(\''.$action->getName().'\') })'; return [ 'x-init' => new HtmlString($attributeValue), @@ -158,7 +159,7 @@ protected function getHeaderActions(): array ]) ->requiresConfirmation() ->modalHeading(function () { - return $this->record->user->fullName . ' has requested to withdraw this submission.'; + return $this->record->user->fullName.' has requested to withdraw this submission.'; }) ->modalDescription("You can either reject the request or accept it, remember it can't be undone.") ->modalCancelActionLabel('Ignore') @@ -173,7 +174,7 @@ protected function getHeaderActions(): array $action->successRedirectUrl( SubmissionResource::getUrl('view', [ 'record' => $this->record, - 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', + 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', ]), ); $action->successNotificationTitle('Withdrawal request rejected'); @@ -193,7 +194,7 @@ protected function getHeaderActions(): array $action->successRedirectUrl( SubmissionResource::getUrl('view', [ 'record' => $this->record, - 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', + 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', ]), ); $action->success(); @@ -205,13 +206,14 @@ protected function getHeaderActions(): array public function getSubheading(): string|Htmlable|null { $badgeHtml = match ($this->record->status) { - SubmissionStatus::Queued => '' . SubmissionStatus::Queued->value . '', - SubmissionStatus::Declined => '' . SubmissionStatus::Declined->value . '', - SubmissionStatus::Withdrawn => '' . SubmissionStatus::Withdrawn->value . '', - SubmissionStatus::Published => '' . SubmissionStatus::Published->value . '', - SubmissionStatus::OnReview => '' . SubmissionStatus::OnReview->value . '', - SubmissionStatus::Incomplete => '' . SubmissionStatus::Incomplete->value . '', - SubmissionStatus::Editing => '' . SubmissionStatus::Editing->value . '', + SubmissionStatus::Incomplete => ''.SubmissionStatus::Incomplete->value.'', + SubmissionStatus::Queued => ''.SubmissionStatus::Queued->value.'', + SubmissionStatus::Payment => ''.SubmissionStatus::Payment->value.'', + SubmissionStatus::OnReview => ''.SubmissionStatus::OnReview->value.'', + SubmissionStatus::Published => ''.SubmissionStatus::Published->value.'', + SubmissionStatus::Editing => ''.SubmissionStatus::Editing->value.'', + SubmissionStatus::Declined => ''.SubmissionStatus::Declined->value.'', + SubmissionStatus::Withdrawn => ''.SubmissionStatus::Withdrawn->value.'', default => null, }; @@ -307,7 +309,7 @@ public function infolist(Infolist $infolist): Infolist LivewireEntry::make('contributors') ->livewire(ContributorList::class, [ 'submission' => $this->record, - 'viewOnly' => !auth()->user()->can('editing', $this->record), + 'viewOnly' => ! auth()->user()->can('editing', $this->record), ]), ]), Tab::make('References') diff --git a/app/Services/Payments/BasePayment.php b/app/Services/Payments/BasePayment.php index cf841796a..6b6a9bdbc 100644 --- a/app/Services/Payments/BasePayment.php +++ b/app/Services/Payments/BasePayment.php @@ -3,9 +3,7 @@ namespace App\Services\Payments; use App\Interfaces\PaymentDriver; -use App\Models\Conference; abstract class BasePayment implements PaymentDriver { - } diff --git a/app/Services/Payments/ManualPayment.php b/app/Services/Payments/ManualPayment.php index dff5de155..2e74d91c7 100644 --- a/app/Services/Payments/ManualPayment.php +++ b/app/Services/Payments/ManualPayment.php @@ -2,9 +2,7 @@ namespace App\Services\Payments; -use App\Interfaces\PaymentDriver; use Filament\Forms\Components\Section; -use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Illuminate\Support\Facades\App; diff --git a/database/migrations/2023_12_12_112200_create_payments_table.php b/database/migrations/2023_12_12_112200_create_payments_table.php index 1a0db45f8..ca5a89a38 100644 --- a/database/migrations/2023_12_12_112200_create_payments_table.php +++ b/database/migrations/2023_12_12_112200_create_payments_table.php @@ -30,7 +30,7 @@ public function up(): void $table->index(['state']); }); - Schema::create('submission_payment_items', function (Blueprint $table){ + Schema::create('submission_payment_items', function (Blueprint $table) { $table->id(); $table->foreignIdFor(Conference::class)->constrained(); $table->string('name'); diff --git a/nohup.out b/nohup.out new file mode 100644 index 000000000..abcfedee6 --- /dev/null +++ b/nohup.out @@ -0,0 +1,313 @@ +Horizon started successfully. + 2023-12-15 10:01:36 App\Mail\Templates\ThankAuthorMail ............. RUNNING + 2023-12-15 10:01:36 App\Mail\Templates\ThankAuthorMail ........ 84.65ms DONE + 2023-12-15 10:01:36 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ........... 34.20ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ........... 24.47ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.43ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.95ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.19ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ........... 17.05ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.87ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.69ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.28ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.16ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.48ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.34ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.14ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.48ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.86ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.36ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 6.73ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.13ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.31ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.31ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 6.85ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.92ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.01ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.52ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ........... 10.24ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.76ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.21ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.49ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.50ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.81ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.83ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.44ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.48ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.38ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.84ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.20ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.12ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.89ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.49ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.64ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.16ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.04ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.25ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.82ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.07ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.20ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.14ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.86ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.54ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.08ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.17ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.92ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 6.97ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ........... 18.88ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 6.64ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ........... 11.24ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 6.69ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.63ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.59ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.16ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.79ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.88ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.88ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.85ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.24ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.09ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ........... 14.14ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.76ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 8.32ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.30ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.20ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.17ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 7.55ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.16ms FAIL + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ........... 10.07ms DONE + 2023-12-15 10:01:37 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:01:37 App\Notifications\NewSubmission ............ 9.47ms FAIL + 2023-12-15 10:02:56 App\Mail\Templates\ThankAuthorMail ............. RUNNING + 2023-12-15 10:02:56 App\Mail\Templates\ThankAuthorMail ........ 30.44ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 13.22ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 11.16ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.19ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.50ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.70ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.67ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.52ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.14ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 21.84ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.98ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.37ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.20ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.92ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.74ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.18ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.60ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 19.38ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.98ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.18ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.22ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.84ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.51ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.18ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 15.58ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 13.57ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 10.37ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 10.22ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.82ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.58ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.15ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.02ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.38ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 6.66ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.79ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.01ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.05ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 13.68ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.55ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.68ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 18.78ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.73ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.87ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 10.57ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.32ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.96ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.29ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.82ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 10.10ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.23ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.21ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.12ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 14.43ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.50ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.68ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.65ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 10.62ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.79ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 11.25ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 10.18ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ........... 10.10ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.72ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.89ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 6.98ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.76ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.00ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.66ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.29ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.08ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.30ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.88ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 7.95ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.74ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 6.90ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.45ms FAIL + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 8.71ms DONE + 2023-12-15 10:02:56 App\Notifications\NewSubmission ................ RUNNING + 2023-12-15 10:02:56 App\Notifications\NewSubmission ............ 9.58ms FAIL + 2023-12-15 10:03:10 App\Notifications\AbstractAccepted ............. RUNNING + 2023-12-15 10:03:10 App\Notifications\AbstractAccepted ........ 93.59ms DONE + 2023-12-15 10:03:10 App\Notifications\AbstractAccepted ............. RUNNING + 2023-12-15 10:03:10 App\Notifications\AbstractAccepted ........ 14.39ms FAIL From 7f03640136d9cc8e948743638c164f1ef7371fd6 Mon Sep 17 00:00:00 2001 From: Rahman Ramsi Date: Tue, 19 Dec 2023 08:27:41 +0800 Subject: [PATCH 5/9] wip --- app/Interfaces/PaymentDriver.php | 5 +- app/Managers/PaymentManager.php | 20 ++- app/Models/Concerns/InteractsWithPayment.php | 18 ++ app/Models/Conference.php | 5 + app/Models/Enums/PaymentState.php | 3 +- app/Models/Enums/SubmissionStage.php | 1 - app/Models/Enums/SubmissionStatus.php | 3 +- app/Models/Interfaces/HasPayment.php | 10 ++ app/Models/Payment.php | 30 +++- .../Interfaces/SubmissionStateInterface.php | 2 - .../States/Submission/BaseSubmissionState.php | 5 - .../Submission/PaymentSubmissionState.php | 2 + .../Submission/QueuedSubmissionState.php | 4 +- app/Models/Submission.php | 8 +- app/Models/SubmissionPaymentItem.php | 21 +++ app/Observers/ConferenceObserver.php | 2 +- app/Panel/Livewire/Submissions/Payment.php | 47 +++++- .../Pages/ViewSubmission.php | 157 +++++++++++++++--- app/Services/Payments/ManualPayment.php | 44 +++-- ...023_12_12_112200_create_payments_table.php | 20 ++- .../livewire/submissions/payment.blade.php | 13 +- 21 files changed, 356 insertions(+), 64 deletions(-) create mode 100644 app/Models/Concerns/InteractsWithPayment.php create mode 100644 app/Models/Interfaces/HasPayment.php diff --git a/app/Interfaces/PaymentDriver.php b/app/Interfaces/PaymentDriver.php index 835d30838..a4253efd3 100644 --- a/app/Interfaces/PaymentDriver.php +++ b/app/Interfaces/PaymentDriver.php @@ -2,6 +2,7 @@ namespace App\Interfaces; +use App\Models\Payment; use Filament\Forms\Form; interface PaymentDriver @@ -10,7 +11,7 @@ public function getName(): string; public function pay($amount, $submission); - public function getPaymentForm(Form $form): Form; + public function getPaymentFormSchema(): array; public function getSettingFormSchema(): array; @@ -18,5 +19,7 @@ public function getSettingFormFill(): array; public function saveSetting(array $data): void; + public function handlePayment(Payment $payment); + // public function fillSettingForm(Form $form): void; } diff --git a/app/Managers/PaymentManager.php b/app/Managers/PaymentManager.php index 5ae255e04..9ab81c0db 100644 --- a/app/Managers/PaymentManager.php +++ b/app/Managers/PaymentManager.php @@ -2,16 +2,19 @@ namespace App\Managers; -use App\Models\Enums\PaymentType; +use App\Models\Interfaces\HasPayment; +use App\Models\Payment; +use App\Models\User; use App\Services\Payments\ManualPayment; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Facades\App; use Illuminate\Support\Manager; class PaymentManager extends Manager { public function getDefaultDriver(): string { - return 'manual'; + return App::getCurrentConference()?->getMeta('workflow.payment.payment_method') ?? 'manual'; } public function createManualDriver() @@ -19,8 +22,19 @@ public function createManualDriver() return new ManualPayment; } - public function createPayment(PaymentType $type, Model $model) + public function createPayment(Model $model, User $user, float $amount, string $currencyId, ?string $paymentMethod = null) { + $payment = $model->payment ?? new Payment; + $payment->amount = $amount; + $payment->currency_id = $currencyId; + $payment->payment_method = $paymentMethod ?? $this->getDefaultDriver(); + if(!$payment->exists){ + $payment->user()->associate($user); + $payment->payable()->associate($model); + } + $payment->save(); + + return $payment; } public function getAllDriverNames() diff --git a/app/Models/Concerns/InteractsWithPayment.php b/app/Models/Concerns/InteractsWithPayment.php new file mode 100644 index 000000000..dea760884 --- /dev/null +++ b/app/Models/Concerns/InteractsWithPayment.php @@ -0,0 +1,18 @@ +morphOne(Payment::class, 'payable'); + } +} diff --git a/app/Models/Conference.php b/app/Models/Conference.php index b175b8d76..81ed4dd8a 100644 --- a/app/Models/Conference.php +++ b/app/Models/Conference.php @@ -159,4 +159,9 @@ public function getHomeUrl(): string default => route('livewirePageGroup.website.pages.home'), }; } + + public function getSupportedCurrencies(): array + { + return $this->getMeta('workflow.payment.supported_currencies') ?? ['usd']; + } } diff --git a/app/Models/Enums/PaymentState.php b/app/Models/Enums/PaymentState.php index 9d89eec6a..eb2530981 100644 --- a/app/Models/Enums/PaymentState.php +++ b/app/Models/Enums/PaymentState.php @@ -10,7 +10,8 @@ enum PaymentState: string implements HasLabel use UsefulEnums; case Pending = 'Pending'; - case Confirmation = 'Confirmation'; + case Processing = 'Processing'; + case Waived = 'Waived'; case Paid = 'Paid'; public function getLabel(): ?string diff --git a/app/Models/Enums/SubmissionStage.php b/app/Models/Enums/SubmissionStage.php index 46d7d15ec..5b6c546db 100644 --- a/app/Models/Enums/SubmissionStage.php +++ b/app/Models/Enums/SubmissionStage.php @@ -11,7 +11,6 @@ enum SubmissionStage: string implements HasLabel case Wizard = 'Wizard'; case CallforAbstract = 'Call for Abstract'; - case Payment = 'Payment'; case PeerReview = 'Peer Review'; case Editing = 'Editing'; case Proceeding = 'Proceeding'; diff --git a/app/Models/Enums/SubmissionStatus.php b/app/Models/Enums/SubmissionStatus.php index 186723cfd..8a5532758 100644 --- a/app/Models/Enums/SubmissionStatus.php +++ b/app/Models/Enums/SubmissionStatus.php @@ -12,7 +12,6 @@ enum SubmissionStatus: string implements HasLabel, HasColor case Incomplete = 'Incomplete'; case Queued = 'Queued'; - case Payment = 'Payment'; case OnReview = 'On Review'; case Editing = 'Editing'; case Published = 'Published'; @@ -30,7 +29,7 @@ public function getColor(): string | array | null return match ($this) { self::Declined, self::Withdrawn => 'danger', self::OnReview => 'warning', - self::Queued, self::Payment => 'primary', + self::Queued => 'primary', self::Editing => 'info', self::Published => 'success', default => 'gray' diff --git a/app/Models/Interfaces/HasPayment.php b/app/Models/Interfaces/HasPayment.php new file mode 100644 index 000000000..a2e8e034f --- /dev/null +++ b/app/Models/Interfaces/HasPayment.php @@ -0,0 +1,10 @@ + PaymentState::class, + 'paid_at' => 'datetime', ]; + + public static function booted() + { + // static::saving(function (Model $model) { + // if($model->state === PaymentState::Paid){ + // $model->paid_at = now(); + // } + // }); + } + + public function payable(): MorphTo + { + return $this->morphTo(); + } + + public function user(): BelongsTo + { + return $this->belongsTo(User::class); + } } diff --git a/app/Models/States/Interfaces/SubmissionStateInterface.php b/app/Models/States/Interfaces/SubmissionStateInterface.php index c9ba00b97..d25fc7495 100644 --- a/app/Models/States/Interfaces/SubmissionStateInterface.php +++ b/app/Models/States/Interfaces/SubmissionStateInterface.php @@ -8,8 +8,6 @@ public function fulfill(): void; public function acceptAbstract(): void; - public function pay(): void; - public function accept(): void; public function publish(): void; diff --git a/app/Models/States/Submission/BaseSubmissionState.php b/app/Models/States/Submission/BaseSubmissionState.php index 971d5ab0d..b0e5bb185 100644 --- a/app/Models/States/Submission/BaseSubmissionState.php +++ b/app/Models/States/Submission/BaseSubmissionState.php @@ -21,11 +21,6 @@ public function acceptAbstract(): void throw new \Exception('Cannot accept abstract'); } - public function pay(): void - { - throw new \Exception('Cannot pay'); - } - public function accept(): void { throw new \Exception('Cannot accept'); diff --git a/app/Models/States/Submission/PaymentSubmissionState.php b/app/Models/States/Submission/PaymentSubmissionState.php index 7630d541c..df9e75920 100644 --- a/app/Models/States/Submission/PaymentSubmissionState.php +++ b/app/Models/States/Submission/PaymentSubmissionState.php @@ -3,6 +3,7 @@ namespace App\Models\States\Submission; use App\Actions\Submissions\SubmissionUpdateAction; +use App\Managers\PaymentManager; use App\Models\Enums\SubmissionStage; use App\Models\Enums\SubmissionStatus; @@ -14,6 +15,7 @@ public function pay(): void 'stage' => SubmissionStage::PeerReview, 'status' => SubmissionStatus::OnReview, ], $this->submission); + } public function withdraw(): void diff --git a/app/Models/States/Submission/QueuedSubmissionState.php b/app/Models/States/Submission/QueuedSubmissionState.php index a12d6111b..3c9e9891f 100644 --- a/app/Models/States/Submission/QueuedSubmissionState.php +++ b/app/Models/States/Submission/QueuedSubmissionState.php @@ -11,8 +11,8 @@ class QueuedSubmissionState extends BaseSubmissionState public function acceptAbstract(): void { SubmissionUpdateAction::run([ - 'stage' => SubmissionStage::Payment, - 'status' => SubmissionStatus::Payment, + 'stage' => SubmissionStage::PeerReview, + 'status' => SubmissionStatus::OnReview, ], $this->submission); } diff --git a/app/Models/Submission.php b/app/Models/Submission.php index 679f66a12..35be3f8e2 100644 --- a/app/Models/Submission.php +++ b/app/Models/Submission.php @@ -4,9 +4,11 @@ use App\Actions\User\CreateParticipantFromUserAction; use App\Models\Concerns\HasTopics; +use App\Models\Concerns\InteractsWithPayment; use App\Models\Enums\SubmissionStage; use App\Models\Enums\SubmissionStatus; use App\Models\Enums\UserRole; +use App\Models\Interfaces\HasPayment; use App\Models\Meta\SubmissionMeta; use App\Models\States\Submission\BaseSubmissionState; use App\Models\States\Submission\DeclinedSubmissionState; @@ -22,6 +24,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\MorphOne; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Auth; use Kra8\Snowflake\HasShortflakePrimary; @@ -30,9 +33,9 @@ use Spatie\MediaLibrary\InteractsWithMedia; use Spatie\Tags\HasTags; -class Submission extends Model implements HasMedia +class Submission extends Model implements HasMedia, HasPayment { - use Cachable, HasFactory, HasShortflakePrimary, HasTags, HasTopics, InteractsWithMedia, Metable; + use Cachable, HasFactory, HasShortflakePrimary, HasTags, HasTopics, InteractsWithMedia, Metable, InteractsWithPayment; /** * The attributes that are mass assignable. @@ -190,7 +193,6 @@ public function state(): BaseSubmissionState return match ($this->status) { SubmissionStatus::Incomplete => new IncompleteSubmissionState($this), SubmissionStatus::Queued => new QueuedSubmissionState($this), - SubmissionStatus::Payment => new PaymentSubmissionState($this), SubmissionStatus::OnReview => new OnReviewSubmissionState($this), SubmissionStatus::Editing => new EditingSubmissionState($this), SubmissionStatus::Published => new PublishedSubmissionState($this), diff --git a/app/Models/SubmissionPaymentItem.php b/app/Models/SubmissionPaymentItem.php index 5e2e65e17..4d6c1b0f5 100644 --- a/app/Models/SubmissionPaymentItem.php +++ b/app/Models/SubmissionPaymentItem.php @@ -2,10 +2,13 @@ namespace App\Models; +use Akaunting\Money\Currency; use App\Models\Concerns\BelongsToConference; use Illuminate\Database\Eloquent\Model; use Spatie\EloquentSortable\Sortable; use Spatie\EloquentSortable\SortableTrait; +use Akaunting\Money; + class SubmissionPaymentItem extends Model implements Sortable { @@ -30,4 +33,22 @@ class SubmissionPaymentItem extends Model implements Sortable protected $casts = [ 'fees' => 'array', ]; + + function getAmount($currencyId) + { + $fee = collect($this->fees)->firstWhere('currency_id', $currencyId); + + if($fee === null) return null; + + return $fee['fee']; + } + + function getFormattedAmount($currencyId) + { + return (new Money\Money( + $this->getAmount($currencyId), + (new Money\Currency(strtoupper($currencyId))), + true + ))->formatWithoutZeroes(); + } } diff --git a/app/Observers/ConferenceObserver.php b/app/Observers/ConferenceObserver.php index 1191b38ff..13ea982b1 100644 --- a/app/Observers/ConferenceObserver.php +++ b/app/Observers/ConferenceObserver.php @@ -56,7 +56,7 @@ public function created(Conference $conference): void ]); $conference->setMeta('page_footer', view('examples.footer')->render()); - $conference->setMeta('workflow.payment.supported_currencies', ['USD']); + $conference->setMeta('workflow.payment.supported_currencies', ['usd']); $conference->save(); } diff --git a/app/Panel/Livewire/Submissions/Payment.php b/app/Panel/Livewire/Submissions/Payment.php index a178d9a72..09bdbbb8d 100644 --- a/app/Panel/Livewire/Submissions/Payment.php +++ b/app/Panel/Livewire/Submissions/Payment.php @@ -3,15 +3,23 @@ namespace App\Panel\Livewire\Submissions; use App\Facades\Payment as PaymentFacade; +use App\Models\Conference; use App\Models\Submission; +use App\Models\SubmissionPaymentItem; use App\Panel\Livewire\Workflows\Classes\StageManager; use App\Panel\Livewire\Workflows\Concerns\InteractWithTenant; use Filament\Actions\Concerns\InteractsWithActions; use Filament\Actions\Contracts\HasActions; +use Filament\Forms\Components\CheckboxList; +use Filament\Forms\Components\Section; +use Filament\Forms\Components\Select; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; +use Filament\Forms\Get; +use Illuminate\Support\Facades\App; use Livewire\Component; +use Squire\Models\Currency; class Payment extends Component implements HasActions, HasForms { @@ -19,6 +27,13 @@ class Payment extends Component implements HasActions, HasForms public Submission $submission; + public array $data = []; + + public function mount() + { + $this->form->fill([]); + } + public function render() { return view('panel.livewire.submissions.payment', [ @@ -29,8 +44,36 @@ public function render() public function form(Form $form) { // return PaymentFacade::getPaymentForm($form); - return $form->schema([ + return $form + ->statePath('data') + ->schema([ + Section::make() + ->schema([ + Select::make('currency_id') + ->label('Currency') + ->options( + Currency::query() + ->whereIn('id', App::getCurrentConference()->getSupportedCurrencies()) + ->get() + ->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name . ' (' . $currency->symbol_native . ')']) + ) + ->required() + ->reactive(), + CheckboxList::make('items') + ->visible(fn (Get $get) => $get('currency_id')) + ->options(function (Get $get) { + return SubmissionPaymentItem::get() + ->filter(function (SubmissionPaymentItem $item) use ($get) : bool { + foreach ($item->fees as $fee) { + if(!array_key_exists('currency_id', $fee)) continue; + if($fee['currency_id'] === $get('currency_id')) return true; + } - ]); + return false; + }) + ->map(fn (SubmissionPaymentItem $item) : string => $item->name . ': ' . $item->getAmount($get('currency_id'))); + }), + ]) + ]); } } diff --git a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php index b4f4b98e8..22fd2e74c 100644 --- a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php +++ b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php @@ -6,12 +6,15 @@ use App\Actions\Submissions\CancelWithdrawalAction; use App\Actions\Submissions\RequestWithdrawalAction; use App\Actions\Submissions\UnpublishSubmissionAction; +use App\Facades\Payment as FacadesPayment; use App\Infolists\Components\LivewireEntry; use App\Infolists\Components\VerticalTabs\Tab as Tab; use App\Infolists\Components\VerticalTabs\Tabs as Tabs; +use App\Models\Enums\PaymentState; use App\Models\Enums\SubmissionStage; use App\Models\Enums\SubmissionStatus; use App\Models\Enums\UserRole; +use App\Models\SubmissionPaymentItem; use App\Models\User; use App\Notifications\SubmissionWithdrawn; use App\Notifications\SubmissionWithdrawRequested; @@ -28,10 +31,17 @@ use App\Panel\Resources\SubmissionResource; use Awcodes\Shout\Components\ShoutEntry; use Filament\Actions\Action; +use Filament\Actions\StaticAction; +use Filament\Forms\Components\CheckboxList; +use Filament\Forms\Components\Grid; +use Filament\Forms\Components\Radio; +use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\TextInput; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; +use Filament\Forms\Get; use Filament\Infolists\Components\Tabs as HorizontalTabs; use Filament\Infolists\Components\Tabs\Tab as HorizontalTab; use Filament\Infolists\Concerns\InteractsWithInfolists; @@ -40,8 +50,10 @@ use Filament\Resources\Pages\Concerns\InteractsWithRecord; use Filament\Resources\Pages\Page; use Illuminate\Contracts\Support\Htmlable; +use Illuminate\Support\Facades\App; use Illuminate\Support\HtmlString; use Illuminate\View\Compilers\BladeCompiler; +use Squire\Models\Currency; class ViewSubmission extends Page implements HasForms, HasInfolists { @@ -63,6 +75,104 @@ public function mount($record): void protected function getHeaderActions(): array { return [ + Action::make('payment') + ->model(Payment::class) + ->record(fn () => $this->record->payment) + ->icon('heroicon-o-currency-dollar') + ->color('primary') + ->when( + fn (Action $action): bool => !$action->getRecord() || $action->getRecord()?->state === PaymentState::Pending, + fn (Action $action): Action => $action + ->action(function (array $data, Form $form) { + $payment = FacadesPayment::createPayment( + $this->record, + auth()->user(), + collect($data['items'])->sum(), + $data['currency_id'], + ); + + $form->model($payment)->saveRelationships(); + + FacadesPayment::driver($this->record->payment?->payment_method)->handlePayment($payment); + })->mountUsing(function (Form $form) { + $payment = $this->record->payment; + + $form->fill([ + 'currency_id' => $payment?->currency_id, + ...FacadesPayment::getPaymentFormFill(), + ]); + })->form([ + Select::make('currency_id') + ->label('Currency') + ->options( + Currency::query() + ->whereIn('id', App::getCurrentConference()->getSupportedCurrencies()) + ->get() + ->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name . ' (' . $currency->symbol_native . ')']) + ) + ->required() + ->reactive(), + CheckboxList::make('items') + ->visible(fn (Get $get) => $get('currency_id')) + ->required() + ->options(function (Get $get) { + return SubmissionPaymentItem::get() + ->filter(function (SubmissionPaymentItem $item) use ($get): bool { + foreach ($item->fees as $fee) { + if (!array_key_exists('currency_id', $fee)) continue; + if ($fee['currency_id'] === $get('currency_id')) return true; + } + + return false; + }) + ->mapWithKeys(fn (SubmissionPaymentItem $item): array => [$item->getAmount($get('currency_id')) => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); + // ->mapWithKeys(fn (SubmissionPaymentItem $item): array => [$item->getKey() => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); + }), + ...FacadesPayment::driver($this->record->payment?->payment_method)->getPaymentFormSchema(), + ]), + ) + ->when( + fn (Action $action): bool => $action->getRecord()?->state === PaymentState::Processing, + fn (Action $action): Action => $action + ->action(function (array $data, $record) { + $record->state = $data['decision']; + $record->save(); + }) + ->modalHeading('Payment Processing') + ->mountUsing(function (Form $form) { + $payment = $this->record->payment; + + $form->fill([ + 'currency_id' => $payment?->currency_id, + 'amount' => $payment?->amount, + ...FacadesPayment::getPaymentFormFill(), + ]); + }) + ->form([ + Grid::make(1) + ->schema([ + Grid::make() + ->schema([ + Select::make('currency_id') + ->label('Currency') + ->options(Currency::pluck('name', 'id')), + TextInput::make('amount') + ->prefix(fn (Get $get) => $get('currency_id') ? Currency::find($get('currency_id'))->symbol_native : null) + ->numeric(), + ]), + + ...FacadesPayment::driver($this->record->payment?->payment_method)->getPaymentFormSchema(), + ]) + ->disabled(), + Select::make('decision') + ->required() + ->options([ + PaymentState::Pending->value => PaymentState::Pending->name, + PaymentState::Waived->value => PaymentState::Waived->name, + PaymentState::Paid->value => PaymentState::Paid->name, + ]), + ]) + ), Action::make('unpublish') ->icon('lineawesome-calendar-times-solid') ->color('danger') @@ -71,11 +181,11 @@ protected function getHeaderActions(): array ->successNotificationTitle('Submission unpublished') ->action(function (Action $action) { $this->record->state()->unpublish(); - + $action->successRedirectUrl( static::getResource()::getUrl('view', [ 'record' => $this->record, - 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', + 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', ]) ); @@ -124,7 +234,7 @@ protected function getHeaderActions(): array $action->successRedirectUrl( SubmissionResource::getUrl('view', [ 'record' => $this->record, - 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', + 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', ]), ); $action->success(); @@ -135,7 +245,7 @@ protected function getHeaderActions(): array ->color('danger') ->extraAttributes(function (Action $action) { if (filled($this->record->withdrawn_reason)) { - $attributeValue = '$nextTick(() => { $wire.mountAction(\''.$action->getName().'\') })'; + $attributeValue = '$nextTick(() => { $wire.mountAction(\'' . $action->getName() . '\') })'; return [ 'x-init' => new HtmlString($attributeValue), @@ -159,7 +269,7 @@ protected function getHeaderActions(): array ]) ->requiresConfirmation() ->modalHeading(function () { - return $this->record->user->fullName.' has requested to withdraw this submission.'; + return $this->record->user->fullName . ' has requested to withdraw this submission.'; }) ->modalDescription("You can either reject the request or accept it, remember it can't be undone.") ->modalCancelActionLabel('Ignore') @@ -174,7 +284,7 @@ protected function getHeaderActions(): array $action->successRedirectUrl( SubmissionResource::getUrl('view', [ 'record' => $this->record, - 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', + 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', ]), ); $action->successNotificationTitle('Withdrawal request rejected'); @@ -194,7 +304,7 @@ protected function getHeaderActions(): array $action->successRedirectUrl( SubmissionResource::getUrl('view', [ 'record' => $this->record, - 'stage' => '-'.str($this->record->stage->value)->slug('-').'-tab', + 'stage' => '-' . str($this->record->stage->value)->slug('-') . '-tab', ]), ); $action->success(); @@ -206,14 +316,13 @@ protected function getHeaderActions(): array public function getSubheading(): string|Htmlable|null { $badgeHtml = match ($this->record->status) { - SubmissionStatus::Incomplete => ''.SubmissionStatus::Incomplete->value.'', - SubmissionStatus::Queued => ''.SubmissionStatus::Queued->value.'', - SubmissionStatus::Payment => ''.SubmissionStatus::Payment->value.'', - SubmissionStatus::OnReview => ''.SubmissionStatus::OnReview->value.'', - SubmissionStatus::Published => ''.SubmissionStatus::Published->value.'', - SubmissionStatus::Editing => ''.SubmissionStatus::Editing->value.'', - SubmissionStatus::Declined => ''.SubmissionStatus::Declined->value.'', - SubmissionStatus::Withdrawn => ''.SubmissionStatus::Withdrawn->value.'', + SubmissionStatus::Incomplete => '' . SubmissionStatus::Incomplete->value . '', + SubmissionStatus::Queued => '' . SubmissionStatus::Queued->value . '', + SubmissionStatus::OnReview => '' . SubmissionStatus::OnReview->value . '', + SubmissionStatus::Published => '' . SubmissionStatus::Published->value . '', + SubmissionStatus::Editing => '' . SubmissionStatus::Editing->value . '', + SubmissionStatus::Declined => '' . SubmissionStatus::Declined->value . '', + SubmissionStatus::Withdrawn => '' . SubmissionStatus::Withdrawn->value . '', default => null, }; @@ -249,14 +358,14 @@ public function infolist(Infolist $infolist): Infolist 'submission' => $this->record, ]), ]), - Tab::make('Payment') - ->icon('heroicon-o-currency-dollar') - ->schema([ - LivewireEntry::make('payment') - ->livewire(Payment::class, [ - 'submission' => $this->record, - ]), - ]), + // Tab::make('Payment') + // ->icon('heroicon-o-currency-dollar') + // ->schema([ + // LivewireEntry::make('payment') + // ->livewire(Payment::class, [ + // 'submission' => $this->record, + // ]), + // ]), Tab::make('Peer Review') ->visible( fn (): bool => StageManager::peerReview()->isStageOpen() @@ -309,7 +418,7 @@ public function infolist(Infolist $infolist): Infolist LivewireEntry::make('contributors') ->livewire(ContributorList::class, [ 'submission' => $this->record, - 'viewOnly' => ! auth()->user()->can('editing', $this->record), + 'viewOnly' => !auth()->user()->can('editing', $this->record), ]), ]), Tab::make('References') diff --git a/app/Services/Payments/ManualPayment.php b/app/Services/Payments/ManualPayment.php index 2e74d91c7..861f4b6c7 100644 --- a/app/Services/Payments/ManualPayment.php +++ b/app/Services/Payments/ManualPayment.php @@ -2,7 +2,10 @@ namespace App\Services\Payments; +use App\Models\Enums\PaymentState; +use App\Models\Payment; use Filament\Forms\Components\Section; +use Filament\Forms\Components\SpatieMediaLibraryFileUpload; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Illuminate\Support\Facades\App; @@ -23,18 +26,37 @@ public function pay($amount, $submission) ]); } - public function getPaymentForm(Form $form): Form + public function handlePayment(Payment $payment) { - return $form->schema([ - Section::make('Payment') - ->schema([ - TextInput::make('payment_amount') - ->label('Payment Amount') - ->placeholder('Payment Amount') - ->required() - ->rules('required', 'numeric'), - ]), - ]); + // Send information to Editor that user is paying the submission + + + // Change payment status to processing + $payment->state = PaymentState::Processing; + $payment->save(); + } + + public function getPaymentFormSchema(): array + { + return [ + TinyEditor::make('instructions') + ->label('Payment Instruction') + ->disabled(), + SpatieMediaLibraryFileUpload::make('payment_proof') + ->collection('payment_proof') + ->label('Payment Proof') + ->required() + ->downloadable(), + ]; + } + + public function getPaymentFormFill(): array + { + $conference = App::getCurrentConference(); + + return [ + 'instructions' => $conference->getMeta('manual_payment.instructions'), + ]; } public function getSettingFormSchema(): array diff --git a/database/migrations/2023_12_12_112200_create_payments_table.php b/database/migrations/2023_12_12_112200_create_payments_table.php index ca5a89a38..335230253 100644 --- a/database/migrations/2023_12_12_112200_create_payments_table.php +++ b/database/migrations/2023_12_12_112200_create_payments_table.php @@ -3,6 +3,7 @@ use App\Models\Conference; use App\Models\Enums\PaymentState; use App\Models\Enums\PaymentType; +use App\Models\User; use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; @@ -17,8 +18,9 @@ public function up(): void Schema::create('payments', function (Blueprint $table) { $table->id(); $table->foreignIdFor(Conference::class)->constrained(); - $table->morphs('model'); - $table->enum('type', PaymentType::array()); + $table->morphs('payable'); + $table->foreignIdFor(User::class)->constrained(); + // $table->enum('type', PaymentType::array()); $table->enum('state', PaymentState::array())->default(PaymentState::Pending->value); $table->double('amount'); $table->string('currency_id'); @@ -26,10 +28,22 @@ public function up(): void $table->string('payment_method'); $table->timestamps(); - $table->index(['type']); + // $table->index(['type']); $table->index(['state']); }); + Schema::create('payment_meta', function (Blueprint $table) { + $table->id(); + $table->string('metable_type'); + $table->unsignedBigInteger('metable_id'); + $table->string('type')->default('null'); + $table->string('key')->index(); + $table->longtext('value'); + + $table->unique(['metable_type', 'metable_id', 'key']); + $table->index(['key', 'metable_type']); + }); + Schema::create('submission_payment_items', function (Blueprint $table) { $table->id(); $table->foreignIdFor(Conference::class)->constrained(); diff --git a/resources/views/panel/livewire/submissions/payment.blade.php b/resources/views/panel/livewire/submissions/payment.blade.php index 38a477472..76d8b74c7 100644 --- a/resources/views/panel/livewire/submissions/payment.blade.php +++ b/resources/views/panel/livewire/submissions/payment.blade.php @@ -3,6 +3,15 @@ use App\Models\Enums\SubmissionStage; use App\Constants\SubmissionFileCategory; @endphp +
- {{ $this->form }} -
+
+
+ {{ $this->form }} +
+
+ side +
+
+ + \ No newline at end of file From 21611019f76f0b05211d3dcb3fc2288a5982f8ca Mon Sep 17 00:00:00 2001 From: Rahman Ramsi Date: Tue, 19 Dec 2023 15:59:46 +0800 Subject: [PATCH 6/9] done --- app/Application.php | 4 +- app/Managers/PaymentManager.php | 40 +++++++---- app/Models/Conference.php | 2 +- app/Models/Enums/Concern/UsefulEnums.php | 5 ++ app/Models/Enums/PaymentState.php | 2 +- app/Models/Enums/PaymentType.php | 1 - app/Models/Meta/PaymentMeta.php | 10 +++ app/Models/Payment.php | 14 +++- ...missionPaymentItem.php => PaymentItem.php} | 6 +- app/Models/Submission.php | 9 +++ .../Livewire/Submissions/Forms/Publish.php | 66 ++++++++++++------- app/Panel/Livewire/Submissions/Payment.php | 8 +-- ...ems.php => SubmissionPaymentItemTable.php} | 31 +++++---- .../Livewire/Workflows/PaymentSetting.php | 54 ++++++++------- app/Panel/Pages/Settings/Workflow.php | 8 +-- .../Pages/ManageSubmissions.php | 3 +- .../Pages/ViewSubmission.php | 56 +++++++++++----- ...023_12_12_112200_create_payments_table.php | 18 ++--- public/build/manifest.json | 2 +- .../workflows/payment-setting.blade.php | 6 -- .../pages/list-submission.blade.php | 21 ++++-- 21 files changed, 236 insertions(+), 130 deletions(-) create mode 100644 app/Models/Meta/PaymentMeta.php rename app/Models/{SubmissionPaymentItem.php => PaymentItem.php} (88%) rename app/Panel/Livewire/Workflows/Payment/Tables/{PaymentItems.php => SubmissionPaymentItemTable.php} (84%) diff --git a/app/Application.php b/app/Application.php index 0022c1b5d..ff4e41873 100644 --- a/app/Application.php +++ b/app/Application.php @@ -8,11 +8,11 @@ use App\Models\Conference; use App\Models\Navigation; use App\Models\ParticipantPosition; +use App\Models\PaymentItem; use App\Models\Scopes\ConferenceScope; use App\Models\Site; use App\Models\StaticPage; use App\Models\Submission; -use App\Models\SubmissionPaymentItem; use App\Models\Timeline; use App\Models\Topic; use App\Models\Venue; @@ -67,7 +67,7 @@ public function scopeCurrentConference(): void Announcement::class, StaticPage::class, Timeline::class, - SubmissionPaymentItem::class, + PaymentItem::class, ] as $model) { $model::addGlobalScope(new ConferenceScope); } diff --git a/app/Managers/PaymentManager.php b/app/Managers/PaymentManager.php index 9ab81c0db..d134d5351 100644 --- a/app/Managers/PaymentManager.php +++ b/app/Managers/PaymentManager.php @@ -2,12 +2,15 @@ namespace App\Managers; +use App\Interfaces\PaymentDriver; use App\Models\Interfaces\HasPayment; use App\Models\Payment; +use App\Models\PaymentItem; use App\Models\User; use App\Services\Payments\ManualPayment; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Manager; class PaymentManager extends Manager @@ -17,27 +20,42 @@ public function getDefaultDriver(): string return App::getCurrentConference()?->getMeta('workflow.payment.payment_method') ?? 'manual'; } - public function createManualDriver() + public function createManualDriver() : PaymentDriver { return new ManualPayment; } - public function createPayment(Model $model, User $user, float $amount, string $currencyId, ?string $paymentMethod = null) + public function createPayment(Model $model, User $user, string $currencyId, array $items, ?string $paymentMethod = null) : Payment { - $payment = $model->payment ?? new Payment; - $payment->amount = $amount; - $payment->currency_id = $currencyId; - $payment->payment_method = $paymentMethod ?? $this->getDefaultDriver(); - if(!$payment->exists){ - $payment->user()->associate($user); - $payment->payable()->associate($model); + try { + DB::beginTransaction(); + + $items = PaymentItem::whereIn('id', $items)->get(); + + $payment = $model->payment ?? new Payment; + $payment->amount = $items->sum(fn($item) => $item->getAmount($currencyId)); + $payment->currency_id = $currencyId; + $payment->payment_method = $paymentMethod ?? $this->getDefaultDriver(); + if(!$payment->exists){ + $payment->user()->associate($user); + $payment->payable()->associate($model); + } + $payment->save(); + + $payment->setMeta('items', $items->map(fn($item) => $item->name . ': ' . $item->getFormattedAmount($currencyId))); + + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + + throw $th; } - $payment->save(); + return $payment; } - public function getAllDriverNames() + public function getAllDriverNames() : \Illuminate\Support\Collection { return collect(['manual', ...$this->customCreators])->mapWithKeys(function ($driver) { return [$driver => $this->driver($driver)->getName()]; diff --git a/app/Models/Conference.php b/app/Models/Conference.php index 81ed4dd8a..5f43441a3 100644 --- a/app/Models/Conference.php +++ b/app/Models/Conference.php @@ -162,6 +162,6 @@ public function getHomeUrl(): string public function getSupportedCurrencies(): array { - return $this->getMeta('workflow.payment.supported_currencies') ?? ['usd']; + return $this->getMeta('payment.supported_currencies') ?? ['usd']; } } diff --git a/app/Models/Enums/Concern/UsefulEnums.php b/app/Models/Enums/Concern/UsefulEnums.php index a40569ba3..111a21b61 100644 --- a/app/Models/Enums/Concern/UsefulEnums.php +++ b/app/Models/Enums/Concern/UsefulEnums.php @@ -23,4 +23,9 @@ public static function random(): static { return self::from(self::values()[array_rand(self::values())]); } + + public function isOneOf(mixed ...$values): bool + { + return in_array($this, $values); + } } diff --git a/app/Models/Enums/PaymentState.php b/app/Models/Enums/PaymentState.php index eb2530981..366bb2806 100644 --- a/app/Models/Enums/PaymentState.php +++ b/app/Models/Enums/PaymentState.php @@ -9,7 +9,7 @@ enum PaymentState: string implements HasLabel { use UsefulEnums; - case Pending = 'Pending'; + case Unpaid = 'Unpaid'; case Processing = 'Processing'; case Waived = 'Waived'; case Paid = 'Paid'; diff --git a/app/Models/Enums/PaymentType.php b/app/Models/Enums/PaymentType.php index 3daaff98c..2e5aceaa5 100644 --- a/app/Models/Enums/PaymentType.php +++ b/app/Models/Enums/PaymentType.php @@ -9,5 +9,4 @@ enum PaymentType: string use UsefulEnums; case Submission = 'Submission'; - case Participant = 'Participant'; } diff --git a/app/Models/Meta/PaymentMeta.php b/app/Models/Meta/PaymentMeta.php new file mode 100644 index 000000000..d0f36ef1b --- /dev/null +++ b/app/Models/Meta/PaymentMeta.php @@ -0,0 +1,10 @@ + PaymentState::Pending, + 'state' => PaymentState::Unpaid, ]; /** @@ -52,4 +53,15 @@ public function user(): BelongsTo { return $this->belongsTo(User::class); } + + protected function getMetaClassName(): string + { + return PaymentMeta::class; + } + + public function isCompleted(): bool + { + return $this->state->isOneOf(PaymentState::Paid, PaymentState::Waived); + } + } diff --git a/app/Models/SubmissionPaymentItem.php b/app/Models/PaymentItem.php similarity index 88% rename from app/Models/SubmissionPaymentItem.php rename to app/Models/PaymentItem.php index 4d6c1b0f5..471f8fdbc 100644 --- a/app/Models/SubmissionPaymentItem.php +++ b/app/Models/PaymentItem.php @@ -8,9 +8,9 @@ use Spatie\EloquentSortable\Sortable; use Spatie\EloquentSortable\SortableTrait; use Akaunting\Money; +use App\Models\Enums\PaymentType; - -class SubmissionPaymentItem extends Model implements Sortable +class PaymentItem extends Model implements Sortable { use BelongsToConference, SortableTrait; @@ -23,6 +23,7 @@ class SubmissionPaymentItem extends Model implements Sortable 'name', 'description', 'fees', + 'type', ]; /** @@ -32,6 +33,7 @@ class SubmissionPaymentItem extends Model implements Sortable */ protected $casts = [ 'fees' => 'array', + 'type' => PaymentType::class, ]; function getAmount($currencyId) diff --git a/app/Models/Submission.php b/app/Models/Submission.php index 35be3f8e2..0e5284693 100644 --- a/app/Models/Submission.php +++ b/app/Models/Submission.php @@ -201,4 +201,13 @@ public function state(): BaseSubmissionState default => throw new \Exception('Invalid submission status'), }; } + + public function hasPaymentProcess() : bool + { + return $this->conference->getMeta('payment.enabled') && match ($this->status) { + SubmissionStatus::OnReview, SubmissionStatus::Editing, SubmissionStatus::Published => true, + SubmissionStatus::Incomplete, SubmissionStatus::Queued, SubmissionStatus::Withdrawn, SubmissionStatus::Declined => false, + default => false, + }; + } } diff --git a/app/Panel/Livewire/Submissions/Forms/Publish.php b/app/Panel/Livewire/Submissions/Forms/Publish.php index 20d614dfc..69ad78d84 100644 --- a/app/Panel/Livewire/Submissions/Forms/Publish.php +++ b/app/Panel/Livewire/Submissions/Forms/Publish.php @@ -24,7 +24,9 @@ use Filament\Infolists\Concerns\InteractsWithInfolists; use Filament\Infolists\Contracts\HasInfolists; use Filament\Infolists\Infolist; +use HTML5; use Illuminate\Support\Facades\Mail; +use Illuminate\Support\HtmlString; use Mohamedsabil83\FilamentFormsTinyeditor\Components\TinyEditor; class Publish extends \Livewire\Component implements HasActions, HasForms, HasInfolists @@ -76,31 +78,45 @@ public function publishAction() ->authorize('publish', $this->submission) ->icon('iconpark-check') ->label('Send to Proceeding') - ->successNotificationTitle('Submission published successfully') - ->mountUsing(function (Form $form) { - $mailTemplate = MailTemplate::where('mailable', PublishSubmissionMail::class)->first(); - $form->fill([ - 'email' => $this->submission->user->email, - 'subject' => $mailTemplate ? $mailTemplate->subject : '', - 'message' => $mailTemplate ? $mailTemplate->html_template : '', - ]); - }) - ->form([ - Fieldset::make('Notification') - ->columns(1) - ->schema([ - TextInput::make('email') - ->disabled() - ->dehydrated(), - TextInput::make('subject') - ->required(), - TinyEditor::make('message') - ->minHeight(300), - Checkbox::make('do-not-notify-author') - ->label("Don't Send Notification to Author"), - ]), - ]) - ->action(fn (Action $action, array $data) => $this->handlePublishAction($action, $data)); + ->when( + fn() => $this->submission->hasPaymentProcess() && !$this->submission->payment?->isCompleted(), + fn (Action $action): Action => $action + ->modalContent(new HtmlString(<<Submission fee has not been paid, please notify the author.

+ HTML)) + ->modalWidth('xl') + ->modalSubmitAction(false) + ) + ->when( + // true, + fn() => !$this->submission->hasPaymentProcess() || $this->submission->payment?->isCompleted(), + fn (Action $action): Action => $action + ->successNotificationTitle('Submission published successfully') + ->mountUsing(function (Form $form) { + $mailTemplate = MailTemplate::where('mailable', PublishSubmissionMail::class)->first(); + $form->fill([ + 'email' => $this->submission->user->email, + 'subject' => $mailTemplate ? $mailTemplate->subject : '', + 'message' => $mailTemplate ? $mailTemplate->html_template : '', + ]); + }) + ->form([ + Fieldset::make('Notification') + ->columns(1) + ->schema([ + TextInput::make('email') + ->disabled() + ->dehydrated(), + TextInput::make('subject') + ->required(), + TinyEditor::make('message') + ->minHeight(300), + Checkbox::make('do-not-notify-author') + ->label("Don't Send Notification to Author"), + ]), + ]) + ->action(fn (Action $action, array $data) => $this->handlePublishAction($action, $data)) + ); } public function infolist(Infolist $infolist): Infolist diff --git a/app/Panel/Livewire/Submissions/Payment.php b/app/Panel/Livewire/Submissions/Payment.php index 09bdbbb8d..5569e17e9 100644 --- a/app/Panel/Livewire/Submissions/Payment.php +++ b/app/Panel/Livewire/Submissions/Payment.php @@ -5,7 +5,7 @@ use App\Facades\Payment as PaymentFacade; use App\Models\Conference; use App\Models\Submission; -use App\Models\SubmissionPaymentItem; +use App\Models\PaymentItem; use App\Panel\Livewire\Workflows\Classes\StageManager; use App\Panel\Livewire\Workflows\Concerns\InteractWithTenant; use Filament\Actions\Concerns\InteractsWithActions; @@ -62,8 +62,8 @@ public function form(Form $form) CheckboxList::make('items') ->visible(fn (Get $get) => $get('currency_id')) ->options(function (Get $get) { - return SubmissionPaymentItem::get() - ->filter(function (SubmissionPaymentItem $item) use ($get) : bool { + return PaymentItem::get() + ->filter(function (PaymentItem $item) use ($get) : bool { foreach ($item->fees as $fee) { if(!array_key_exists('currency_id', $fee)) continue; if($fee['currency_id'] === $get('currency_id')) return true; @@ -71,7 +71,7 @@ public function form(Form $form) return false; }) - ->map(fn (SubmissionPaymentItem $item) : string => $item->name . ': ' . $item->getAmount($get('currency_id'))); + ->map(fn (PaymentItem $item) : string => $item->name . ': ' . $item->getAmount($get('currency_id'))); }), ]) ]); diff --git a/app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php b/app/Panel/Livewire/Workflows/Payment/Tables/SubmissionPaymentItemTable.php similarity index 84% rename from app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php rename to app/Panel/Livewire/Workflows/Payment/Tables/SubmissionPaymentItemTable.php index 7259c4f60..06e0f2488 100644 --- a/app/Panel/Livewire/Workflows/Payment/Tables/PaymentItems.php +++ b/app/Panel/Livewire/Workflows/Payment/Tables/SubmissionPaymentItemTable.php @@ -2,9 +2,11 @@ namespace App\Panel\Livewire\Workflows\Payment\Tables; -use App\Models\SubmissionPaymentItem; +use App\Models\Enums\PaymentType; +use App\Models\PaymentItem; use App\Tables\Columns\IndexColumn; use Filament\Forms\Components\Grid; +use Filament\Forms\Components\Hidden; use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; @@ -23,7 +25,7 @@ use Illuminate\Support\Facades\App; use Squire\Models\Currency; -class PaymentItems extends \Livewire\Component implements HasForms, HasTable +class SubmissionPaymentItemTable extends \Livewire\Component implements HasForms, HasTable { use InteractsWithForms; use InteractsWithTable; @@ -36,6 +38,7 @@ public function render() public function table(Table $table): Table { $formField = [ + Hidden::make('type'), TextInput::make('name') ->required(), Textarea::make('description') @@ -51,7 +54,6 @@ public function table(Table $table): Table ->required() ->disabled() ->dehydrated(true) - // ->options(Currency::whereIn('id', App::getCurrentConference()->getMeta('workflow.payment.supported_currencies') ?? [])->pluck('name', 'id')) ->options(Currency::pluck('name', 'id')) ->optionsLimit(250) ->distinct(), @@ -64,15 +66,17 @@ public function table(Table $table): Table ]) ->deletable(false) ->reorderable(false) - // ->reorderableWithButtons() ->addable(false) ->addActionLabel('Add Fee'), ]; return $table - ->query(SubmissionPaymentItem::query()) + ->query( + PaymentItem::query() + ->where('type', PaymentType::Submission) + ->orderBy('order_column') + ) ->reorderable('order_column') - ->heading('Payment Items') ->paginated(false) ->columns([ IndexColumn::make('no'), @@ -86,17 +90,18 @@ public function table(Table $table): Table CreateAction::make() ->label('New Payment Item') ->mountUsing(function (Form $form) { - $fees = collect(App::getCurrentConference()->getMeta('workflow.payment.supported_currencies'))->map(function ($currency) { - return [ + $fees = collect(App::getCurrentConference()->getMeta('payment.supported_currencies')) + ->map(fn ($currency) => [ 'currency_id' => $currency, 'fee' => 0, - ]; - })->toArray(); + ]); + $form->fill([ - 'fees' => $fees, + 'fees' => $fees->toArray(), + 'type' => PaymentType::Submission, ]); }) - ->model(SubmissionPaymentItem::class) + ->model(PaymentItem::class) ->modalWidth('2xl') ->form($formField), ]) @@ -106,7 +111,7 @@ public function table(Table $table): Table ->actions([ EditAction::make() ->mutateRecordDataUsing(function ($data) { - $supportedCurrencies = App::getCurrentConference()->getMeta('workflow.payment.supported_currencies') ?? []; + $supportedCurrencies = App::getCurrentConference()->getMeta('payment.supported_currencies') ?? []; $fees = collect($supportedCurrencies) ->map(fn ($currency) => ['currency_id' => $currency, 'fee' => 0]) ->keyBy('currency_id') diff --git a/app/Panel/Livewire/Workflows/PaymentSetting.php b/app/Panel/Livewire/Workflows/PaymentSetting.php index c3139eb08..d3f1c2a64 100644 --- a/app/Panel/Livewire/Workflows/PaymentSetting.php +++ b/app/Panel/Livewire/Workflows/PaymentSetting.php @@ -10,10 +10,12 @@ use Filament\Actions\Contracts\HasActions; use Filament\Forms\Components\Grid; use Filament\Forms\Components\Select; +use Filament\Forms\Components\Toggle; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; use Filament\Forms\Get; +use Illuminate\Support\Arr; use Illuminate\Support\Facades\Log; use Squire\Models\Currency; @@ -30,9 +32,10 @@ class PaymentSetting extends WorkflowStage implements HasActions, HasForms public function mount() { $this->form->fill([ - 'settings' => [ - 'payment_method' => $this->getSetting('payment_method', 'manual'), - 'supported_currencies' => $this->getSetting('supported_currencies'), + 'payment' => [ + 'enabled' => $this->conference->getMeta('payment.enabled'), + 'method' => $this->conference->getMeta('payment.method', 'manual'), + 'supported_currencies' => $this->conference->getMeta('payment.supported_currencies', ['usd']), ], ...Payment::getAllDriverNames()->map(fn ($name, $key) => Payment::driver($key)->getSettingFormFill())->toArray(), ]); @@ -50,14 +53,15 @@ public function submitAction() try { $data = $this->form->getState(); - foreach ($data['settings'] as $key => $value) { - $this->updateSetting($key, $value); + + foreach ($data['payment'] as $key => $value) { + $this->conference->setMeta('payment.' . $key, $value); } - Payment::driver($data['settings']['payment_method']) - ->saveSetting(data_get($data, $data['settings']['payment_method'], [])); + Payment::driver($this->conference->getMeta('payment.method')) + ->saveSetting(data_get($data, $this->conference->getMeta('payment.method'), [])); } catch (\Throwable $th) { - //throw $th; + Log::error($th); $action->failure(); @@ -73,24 +77,26 @@ public function form(Form $form): Form return $form ->statePath('data') ->schema([ - Shout::make('stage-closed') - ->hidden(fn (): bool => $this->isStageOpen()) - ->color('warning') - ->content('The payment stage is not open yet, Start now or schedule opening'), - Select::make('settings.payment_method') - ->label('Payment Method') - ->required() - ->options(Payment::getAllDriverNames()) + Toggle::make('payment.enabled') ->reactive(), - Select::make('settings.supported_currencies') - ->searchable() - ->required() - ->multiple() - ->options(Currency::query()->get()->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name.' ('.$currency->symbol_native.')'])->toArray()) - ->optionsLimit(250), Grid::make(1) - ->hidden(fn (Get $get) => ! $get('settings.payment_method')) - ->schema(fn (Get $get) => Payment::driver($get('payment_method'))->getSettingFormSchema()), + ->hidden(fn (Get $get) => ! $get('payment.enabled')) + ->schema([ + Select::make('payment.method') + ->label('Payment Method') + ->required() + ->options(Payment::getAllDriverNames()) + ->reactive(), + Select::make('payment.supported_currencies') + ->searchable() + ->required() + ->multiple() + ->options(Currency::query()->get()->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name.' ('.$currency->symbol_native.')'])->toArray()) + ->optionsLimit(250), + Grid::make(1) + ->hidden(fn (Get $get) => !$get('payment.method')) + ->schema(fn (Get $get) => Payment::driver($get('payment.method'))->getSettingFormSchema()), + ]) ]); } diff --git a/app/Panel/Pages/Settings/Workflow.php b/app/Panel/Pages/Settings/Workflow.php index 2b0b466d5..07538a72a 100644 --- a/app/Panel/Pages/Settings/Workflow.php +++ b/app/Panel/Pages/Settings/Workflow.php @@ -7,7 +7,7 @@ use App\Infolists\Components\VerticalTabs\Tabs; use App\Panel\Livewire\Workflows\AbstractSetting; use App\Panel\Livewire\Workflows\EditingSetting; -use App\Panel\Livewire\Workflows\Payment\Tables\PaymentItems; +use App\Panel\Livewire\Workflows\Payment\Tables\SubmissionPaymentItemTable; use App\Panel\Livewire\Workflows\PaymentSetting; use App\Panel\Livewire\Workflows\PeerReview\Forms\Guidelines; use App\Panel\Livewire\Workflows\PeerReviewSetting; @@ -35,7 +35,7 @@ class Workflow extends Page implements HasForms, HasInfolists public function booted(): void { - abort_if(! static::canView(), 403); + abort_if(!static::canView(), 403); } public static function shouldRegisterNavigation(): bool @@ -77,10 +77,10 @@ public function infolist(Infolist $infolist): Infolist LivewireEntry::make('payment-setting') ->livewire(PaymentSetting::class), ]), - HorizontalTab::make('Items') + HorizontalTab::make('Submission Payment Items') ->schema([ LivewireEntry::make('payment-items') - ->livewire(PaymentItems::class), + ->livewire(SubmissionPaymentItemTable::class), ]), ]), diff --git a/app/Panel/Resources/SubmissionResource/Pages/ManageSubmissions.php b/app/Panel/Resources/SubmissionResource/Pages/ManageSubmissions.php index 901b07256..5e4bcb2ad 100644 --- a/app/Panel/Resources/SubmissionResource/Pages/ManageSubmissions.php +++ b/app/Panel/Resources/SubmissionResource/Pages/ManageSubmissions.php @@ -10,12 +10,13 @@ use Awcodes\Shout\Components\ShoutEntry; use Filament\Actions\Action; use Filament\Infolists\Infolist; -use Filament\Resources\Pages\ListRecords\Tab; +use Filament\Resources\Components\Tab; use Filament\Resources\Pages\ManageRecords; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\Auth; use Illuminate\Support\HtmlString; + class ManageSubmissions extends ManageRecords { protected static string $resource = SubmissionResource::class; diff --git a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php index 2efcd26f8..1e7ed8834 100644 --- a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php +++ b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php @@ -14,7 +14,7 @@ use App\Models\Enums\SubmissionStage; use App\Models\Enums\SubmissionStatus; use App\Models\Enums\UserRole; -use App\Models\SubmissionPaymentItem; +use App\Models\PaymentItem; use App\Models\User; use App\Notifications\SubmissionWithdrawn; use App\Notifications\SubmissionWithdrawRequested; @@ -76,19 +76,22 @@ protected function getHeaderActions(): array { return [ Action::make('payment') - ->model(Payment::class) + ->visible($this->record->hasPaymentProcess()) ->record(fn () => $this->record->payment) + ->model(Payment::class) ->icon('heroicon-o-currency-dollar') ->color('primary') + ->modalHeading('Submission Payment') ->when( - fn (Action $action): bool => !$action->getRecord() || $action->getRecord()?->state === PaymentState::Pending, + fn (Action $action): bool => !$action->getRecord() || $action->getRecord()?->state->isOneOf(PaymentState::Unpaid), fn (Action $action): Action => $action ->action(function (array $data, Form $form) { + $payment = FacadesPayment::createPayment( $this->record, auth()->user(), - collect($data['items'])->sum(), $data['currency_id'], + $data['items'], ); $form->model($payment)->saveRelationships(); @@ -116,8 +119,8 @@ protected function getHeaderActions(): array ->visible(fn (Get $get) => $get('currency_id')) ->required() ->options(function (Get $get) { - return SubmissionPaymentItem::get() - ->filter(function (SubmissionPaymentItem $item) use ($get): bool { + return PaymentItem::get() + ->filter(function (PaymentItem $item) use ($get): bool { foreach ($item->fees as $fee) { if (!array_key_exists('currency_id', $fee)) continue; if ($fee['currency_id'] === $get('currency_id')) return true; @@ -125,26 +128,28 @@ protected function getHeaderActions(): array return false; }) - ->mapWithKeys(fn (SubmissionPaymentItem $item): array => [$item->getAmount($get('currency_id')) => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); - // ->mapWithKeys(fn (SubmissionPaymentItem $item): array => [$item->getKey() => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); + // ->mapWithKeys(fn (PaymentItem $item): array => [$item->getAmount($get('currency_id')) => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); + ->mapWithKeys(fn (PaymentItem $item): array => [$item->id => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); }), ...FacadesPayment::driver($this->record->payment?->payment_method)->getPaymentFormSchema(), ]), ) ->when( - fn (Action $action): bool => $action->getRecord()?->state === PaymentState::Processing, + fn (Action $action): bool => $action->getRecord()?->state->isOneOf(PaymentState::Processing, PaymentState::Paid, PaymentState::Waived) ?? false, fn (Action $action): Action => $action ->action(function (array $data, $record) { $record->state = $data['decision']; $record->save(); }) - ->modalHeading('Payment Processing') + ->modalSubmitAction(fn(StaticAction $action) => $action->hidden($this->record->payment?->isCompleted())) + ->modalCancelAction(fn(StaticAction $action) => $action->hidden($this->record->payment?->isCompleted())) ->mountUsing(function (Form $form) { $payment = $this->record->payment; $form->fill([ 'currency_id' => $payment?->currency_id, 'amount' => $payment?->amount, + 'items' => array_keys($payment?->getMeta('items') ?? []), ...FacadesPayment::getPaymentFormFill(), ]); }) @@ -160,14 +165,17 @@ protected function getHeaderActions(): array ->prefix(fn (Get $get) => $get('currency_id') ? Currency::find($get('currency_id'))->symbol_native : null) ->numeric(), ]), + CheckboxList::make('items') + ->options($this->record->payment?->getMeta('items')), ...FacadesPayment::driver($this->record->payment?->payment_method)->getPaymentFormSchema(), ]) ->disabled(), Select::make('decision') ->required() + ->hidden(fn() => $this->record->payment?->isCompleted()) ->options([ - PaymentState::Pending->value => PaymentState::Pending->name, + PaymentState::Unpaid->value => PaymentState::Unpaid->name, PaymentState::Waived->value => PaymentState::Waived->name, PaymentState::Paid->value => PaymentState::Paid->name, ]), @@ -221,7 +229,9 @@ protected function getHeaderActions(): array fn ($manager) => $manager->notify(new SubmissionWithdrawRequested($this->record)) ); - $this->record->getEditors() + $this + ->record + ->getEditors() ->each(function (User $editor) { $editor->notify(new SubmissionWithdrawRequested($this->record)); }); @@ -311,7 +321,9 @@ protected function getHeaderActions(): array public function getSubheading(): string|Htmlable|null { - $badgeHtml = match ($this->record->status) { + $badgeHtml = '
'; + + $badgeHtml .= match ($this->record->status) { SubmissionStatus::Incomplete => '' . SubmissionStatus::Incomplete->value . '', SubmissionStatus::Queued => '' . SubmissionStatus::Queued->value . '', SubmissionStatus::OnReview => '' . SubmissionStatus::OnReview->value . '', @@ -322,6 +334,18 @@ public function getSubheading(): string|Htmlable|null default => null, }; + if ($this->record->hasPaymentProcess()) { + $badgeHtml .= match ($this->record->payment?->state) { + PaymentState::Unpaid => 'Unpaid', + PaymentState::Processing => 'Payment Processing', + PaymentState::Paid => 'Paid', + PaymentState::Waived => 'Payment Waived', + default => 'Unpaid', + }; + } + + $badgeHtml .= '
'; + return new HtmlString( BladeCompiler::render($badgeHtml) ); @@ -357,7 +381,7 @@ public function infolist(Infolist $infolist): Infolist Tab::make('Call for Abstract') ->icon('heroicon-o-information-circle') ->schema(function () { - if (! StageManager::callForAbstract()->isStageOpen() && ! $this->record->isPublished()) { + if (!StageManager::callForAbstract()->isStageOpen() && !$this->record->isPublished()) { return [ ShoutEntry::make('call-for-abstract-closed') ->type('warning') @@ -376,7 +400,7 @@ public function infolist(Infolist $infolist): Infolist Tab::make('Peer Review') ->icon('iconpark-checklist-o') ->schema(function (): array { - if (! StageManager::peerReview()->isStageOpen() && ! $this->record->isPublished()) { + if (!StageManager::peerReview()->isStageOpen() && !$this->record->isPublished()) { return [ ShoutEntry::make('peer-review-closed') ->type('warning') @@ -395,7 +419,7 @@ public function infolist(Infolist $infolist): Infolist Tab::make('Editing') ->icon('heroicon-o-pencil') ->schema(function () { - if (! StageManager::editing()->isStageOpen() && ! $this->record->isPublished()) { + if (!StageManager::editing()->isStageOpen() && !$this->record->isPublished()) { return [ ShoutEntry::make('editing-closed') ->type('warning') diff --git a/database/migrations/2023_12_12_112200_create_payments_table.php b/database/migrations/2023_12_12_112200_create_payments_table.php index 335230253..6e909f5b3 100644 --- a/database/migrations/2023_12_12_112200_create_payments_table.php +++ b/database/migrations/2023_12_12_112200_create_payments_table.php @@ -20,15 +20,15 @@ public function up(): void $table->foreignIdFor(Conference::class)->constrained(); $table->morphs('payable'); $table->foreignIdFor(User::class)->constrained(); - // $table->enum('type', PaymentType::array()); - $table->enum('state', PaymentState::array())->default(PaymentState::Pending->value); + $table->enum('type', PaymentType::array()); + $table->enum('state', PaymentState::array())->default(PaymentState::Unpaid->value); $table->double('amount'); $table->string('currency_id'); $table->timestamp('paid_at')->nullable(); $table->string('payment_method'); $table->timestamps(); - // $table->index(['type']); + $table->index(['type']); $table->index(['state']); }); @@ -44,25 +44,17 @@ public function up(): void $table->index(['key', 'metable_type']); }); - Schema::create('submission_payment_items', function (Blueprint $table) { + Schema::create('payment_items', function (Blueprint $table) { $table->id(); $table->foreignIdFor(Conference::class)->constrained(); $table->string('name'); + $table->enum('type', PaymentType::array()); $table->text('description')->nullable(); $table->integer('order_column')->nullable(); $table->json('fees'); $table->boolean('active')->default(true); $table->timestamps(); }); - - // Schema::create('submission_payment_items_details', function (Blueprint $table){ - // $table->id(); - // $table->foreignId('submission_payment_item_id')->constrained('submission_payment_items', indexName:'items_details_item_id_foreign')->cascadeOnDelete(); - // $table->string('currency_id'); - // $table->double('fee'); - // $table->integer('order_column')->nullable(); - // $table->timestamps(); - // }); } /** diff --git a/public/build/manifest.json b/public/build/manifest.json index f3e3596e9..e72c1d415 100644 --- a/public/build/manifest.json +++ b/public/build/manifest.json @@ -4,7 +4,7 @@ "src": "resources/assets/images/logo.png" }, "resources/panel/css/panel.css": { - "file": "assets/panel-df6f1873.css", + "file": "assets/panel-c1c13b63.css", "isEntry": true, "src": "resources/panel/css/panel.css" }, diff --git a/resources/views/panel/livewire/workflows/payment-setting.blade.php b/resources/views/panel/livewire/workflows/payment-setting.blade.php index 268bc8199..39a7451e8 100644 --- a/resources/views/panel/livewire/workflows/payment-setting.blade.php +++ b/resources/views/panel/livewire/workflows/payment-setting.blade.php @@ -4,13 +4,7 @@

Payment

- @if ($this->isStageOpen()) - Open - @else - Close - @endif - @livewire(App\Panel\Livewire\Workflows\Components\StageSchedule::class, ['stage' => $this->getStage()])
{{ $this->form }} diff --git a/resources/views/panel/resources/submission-resource/pages/list-submission.blade.php b/resources/views/panel/resources/submission-resource/pages/list-submission.blade.php index 3f59a6eee..c64e32151 100644 --- a/resources/views/panel/resources/submission-resource/pages/list-submission.blade.php +++ b/resources/views/panel/resources/submission-resource/pages/list-submission.blade.php @@ -1,4 +1,17 @@ - - {{ $this->infolist }} - {{ $this->table }} - +getResource()::getSlug()), + ]) +> +
+ + + {{ \Filament\Support\Facades\FilamentView::renderHook('panels::resource.pages.list-records.table.before', scopes: $this->getRenderHookScopes()) }} + + {{ $this->infolist }} + {{ $this->table }} + + {{ \Filament\Support\Facades\FilamentView::renderHook('panels::resource.pages.list-records.table.after', scopes: $this->getRenderHookScopes()) }} +
+
From d5997f2ced905741fd51710e74bb8e749a4fbc65 Mon Sep 17 00:00:00 2001 From: Rahman Ramsi Date: Wed, 20 Dec 2023 11:58:53 +0800 Subject: [PATCH 7/9] fix error when third party payment is disabled --- app/Interfaces/PaymentDriver.php | 2 - app/Managers/PaymentManager.php | 39 ++++++++---- app/Models/Concerns/InteractsWithPayment.php | 4 -- app/Models/Enums/SubmissionStatus.php | 4 +- app/Models/Interfaces/HasPayment.php | 6 +- app/Models/Payment.php | 3 +- app/Models/PaymentItem.php | 13 ++-- .../Submission/DeclinedSubmissionState.php | 5 -- .../Submission/PaymentSubmissionState.php | 1 - .../Submission/QueuedSubmissionState.php | 2 +- app/Models/Submission.php | 6 +- .../Livewire/Submissions/CallforAbstract.php | 13 ++-- .../Livewire/Submissions/Forms/Publish.php | 60 +++++++++---------- app/Panel/Livewire/Submissions/Payment.php | 19 +++--- .../Livewire/Workflows/PaymentSetting.php | 18 +++--- app/Panel/Pages/Settings/Workflow.php | 2 +- .../Pages/ManageSubmissions.php | 1 - .../Pages/ViewSubmission.php | 57 +++++++++--------- app/Providers/AppServiceProvider.php | 6 ++ app/Services/Payments/ManualPayment.php | 12 ---- app/Services/Payments/PaypalPayment.php | 48 +++++++++++++++ 21 files changed, 180 insertions(+), 141 deletions(-) create mode 100644 app/Services/Payments/PaypalPayment.php diff --git a/app/Interfaces/PaymentDriver.php b/app/Interfaces/PaymentDriver.php index a4253efd3..13e1fb28e 100644 --- a/app/Interfaces/PaymentDriver.php +++ b/app/Interfaces/PaymentDriver.php @@ -9,8 +9,6 @@ interface PaymentDriver { public function getName(): string; - public function pay($amount, $submission); - public function getPaymentFormSchema(): array; public function getSettingFormSchema(): array; diff --git a/app/Managers/PaymentManager.php b/app/Managers/PaymentManager.php index d134d5351..d88bf7f6d 100644 --- a/app/Managers/PaymentManager.php +++ b/app/Managers/PaymentManager.php @@ -3,7 +3,6 @@ namespace App\Managers; use App\Interfaces\PaymentDriver; -use App\Models\Interfaces\HasPayment; use App\Models\Payment; use App\Models\PaymentItem; use App\Models\User; @@ -17,32 +16,32 @@ class PaymentManager extends Manager { public function getDefaultDriver(): string { - return App::getCurrentConference()?->getMeta('workflow.payment.payment_method') ?? 'manual'; + return App::getCurrentConference()?->getMeta('payment.method') ?? 'manual'; } - public function createManualDriver() : PaymentDriver + public function createManualDriver(): PaymentDriver { return new ManualPayment; } - public function createPayment(Model $model, User $user, string $currencyId, array $items, ?string $paymentMethod = null) : Payment + public function createPayment(Model $model, User $user, string $currencyId, array $items, ?string $paymentMethod = null): Payment { try { DB::beginTransaction(); $items = PaymentItem::whereIn('id', $items)->get(); - + $payment = $model->payment ?? new Payment; - $payment->amount = $items->sum(fn($item) => $item->getAmount($currencyId)); + $payment->amount = $items->sum(fn ($item) => $item->getAmount($currencyId)); $payment->currency_id = $currencyId; $payment->payment_method = $paymentMethod ?? $this->getDefaultDriver(); - if(!$payment->exists){ + if (! $payment->exists) { $payment->user()->associate($user); $payment->payable()->associate($model); } $payment->save(); - $payment->setMeta('items', $items->map(fn($item) => $item->name . ': ' . $item->getFormattedAmount($currencyId))); + $payment->setMeta('items', $items->map(fn ($item) => $item->name.': '.$item->getFormattedAmount($currencyId))); DB::commit(); } catch (\Throwable $th) { @@ -51,14 +50,30 @@ public function createPayment(Model $model, User $user, string $currencyId, arra throw $th; } - return $payment; } - public function getAllDriverNames() : \Illuminate\Support\Collection + public function getAllDriverNames(): \Illuminate\Support\Collection { - return collect(['manual', ...$this->customCreators])->mapWithKeys(function ($driver) { - return [$driver => $this->driver($driver)->getName()]; + return collect(['manual' => 'manual', ...$this->customCreators])->mapWithKeys(function ($driver, $key) { + return [$key => $this->driver($key)->getName()]; }); } + + /** + * Create a new driver instance. + * + * @param string $driver + * @return mixed + * + * @throws \InvalidArgumentException + */ + protected function createDriver($driver) + { + try { + return parent::createDriver($driver); + } catch (\Throwable $th) { + return null; + } + } } diff --git a/app/Models/Concerns/InteractsWithPayment.php b/app/Models/Concerns/InteractsWithPayment.php index dea760884..a5c6b2837 100644 --- a/app/Models/Concerns/InteractsWithPayment.php +++ b/app/Models/Concerns/InteractsWithPayment.php @@ -3,11 +3,7 @@ namespace App\Models\Concerns; use App\Models\Payment; -use App\Models\Topic; -use ArrayAccess; -use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphOne; -use Illuminate\Database\Eloquent\Relations\MorphToMany; trait InteractsWithPayment { diff --git a/app/Models/Enums/SubmissionStatus.php b/app/Models/Enums/SubmissionStatus.php index 8a5532758..84e02c881 100644 --- a/app/Models/Enums/SubmissionStatus.php +++ b/app/Models/Enums/SubmissionStatus.php @@ -6,7 +6,7 @@ use Filament\Support\Contracts\HasColor; use Filament\Support\Contracts\HasLabel; -enum SubmissionStatus: string implements HasLabel, HasColor +enum SubmissionStatus: string implements HasColor, HasLabel { use UsefulEnums; @@ -24,7 +24,7 @@ public function getLabel(): ?string return $this->name; } - public function getColor(): string | array | null + public function getColor(): string|array|null { return match ($this) { self::Declined, self::Withdrawn => 'danger', diff --git a/app/Models/Interfaces/HasPayment.php b/app/Models/Interfaces/HasPayment.php index a2e8e034f..2bf06945e 100644 --- a/app/Models/Interfaces/HasPayment.php +++ b/app/Models/Interfaces/HasPayment.php @@ -4,7 +4,7 @@ use Illuminate\Database\Eloquent\Relations\MorphOne; -interface HasPayment +interface HasPayment { - public function payment() : MorphOne; -} \ No newline at end of file + public function payment(): MorphOne; +} diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 0aad4fd12..d881028f3 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -14,7 +14,7 @@ class Payment extends Model implements HasMedia { - use Metable, InteractsWithMedia, BelongsToConference; + use BelongsToConference, InteractsWithMedia, Metable; /** * The model's default values for attributes. @@ -63,5 +63,4 @@ public function isCompleted(): bool { return $this->state->isOneOf(PaymentState::Paid, PaymentState::Waived); } - } diff --git a/app/Models/PaymentItem.php b/app/Models/PaymentItem.php index 471f8fdbc..a5332a64b 100644 --- a/app/Models/PaymentItem.php +++ b/app/Models/PaymentItem.php @@ -2,13 +2,12 @@ namespace App\Models; -use Akaunting\Money\Currency; +use Akaunting\Money; use App\Models\Concerns\BelongsToConference; +use App\Models\Enums\PaymentType; use Illuminate\Database\Eloquent\Model; use Spatie\EloquentSortable\Sortable; use Spatie\EloquentSortable\SortableTrait; -use Akaunting\Money; -use App\Models\Enums\PaymentType; class PaymentItem extends Model implements Sortable { @@ -36,16 +35,18 @@ class PaymentItem extends Model implements Sortable 'type' => PaymentType::class, ]; - function getAmount($currencyId) + public function getAmount($currencyId) { $fee = collect($this->fees)->firstWhere('currency_id', $currencyId); - if($fee === null) return null; + if ($fee === null) { + return null; + } return $fee['fee']; } - function getFormattedAmount($currencyId) + public function getFormattedAmount($currencyId) { return (new Money\Money( $this->getAmount($currencyId), diff --git a/app/Models/States/Submission/DeclinedSubmissionState.php b/app/Models/States/Submission/DeclinedSubmissionState.php index 2e8870e2f..6d3a5c791 100644 --- a/app/Models/States/Submission/DeclinedSubmissionState.php +++ b/app/Models/States/Submission/DeclinedSubmissionState.php @@ -2,11 +2,6 @@ namespace App\Models\States\Submission; -use App\Actions\Submissions\SubmissionUpdateAction; -use App\Models\Enums\SubmissionStage; -use App\Models\Enums\SubmissionStatus; - class DeclinedSubmissionState extends BaseSubmissionState { - } diff --git a/app/Models/States/Submission/PaymentSubmissionState.php b/app/Models/States/Submission/PaymentSubmissionState.php index df9e75920..80040e88e 100644 --- a/app/Models/States/Submission/PaymentSubmissionState.php +++ b/app/Models/States/Submission/PaymentSubmissionState.php @@ -3,7 +3,6 @@ namespace App\Models\States\Submission; use App\Actions\Submissions\SubmissionUpdateAction; -use App\Managers\PaymentManager; use App\Models\Enums\SubmissionStage; use App\Models\Enums\SubmissionStatus; diff --git a/app/Models/States/Submission/QueuedSubmissionState.php b/app/Models/States/Submission/QueuedSubmissionState.php index 3c9e9891f..67aa6e5cf 100644 --- a/app/Models/States/Submission/QueuedSubmissionState.php +++ b/app/Models/States/Submission/QueuedSubmissionState.php @@ -16,7 +16,7 @@ public function acceptAbstract(): void ], $this->submission); } - public function decline():void + public function decline(): void { SubmissionUpdateAction::run([ 'status' => SubmissionStatus::Declined, diff --git a/app/Models/Submission.php b/app/Models/Submission.php index 0e5284693..b9f745078 100644 --- a/app/Models/Submission.php +++ b/app/Models/Submission.php @@ -15,7 +15,6 @@ use App\Models\States\Submission\EditingSubmissionState; use App\Models\States\Submission\IncompleteSubmissionState; use App\Models\States\Submission\OnReviewSubmissionState; -use App\Models\States\Submission\PaymentSubmissionState; use App\Models\States\Submission\PublishedSubmissionState; use App\Models\States\Submission\QueuedSubmissionState; use App\Models\States\Submission\WithdrawnSubmissionState; @@ -24,7 +23,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\Relations\MorphOne; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Auth; use Kra8\Snowflake\HasShortflakePrimary; @@ -35,7 +33,7 @@ class Submission extends Model implements HasMedia, HasPayment { - use Cachable, HasFactory, HasShortflakePrimary, HasTags, HasTopics, InteractsWithMedia, Metable, InteractsWithPayment; + use Cachable, HasFactory, HasShortflakePrimary, HasTags, HasTopics, InteractsWithMedia, InteractsWithPayment, Metable; /** * The attributes that are mass assignable. @@ -202,7 +200,7 @@ public function state(): BaseSubmissionState }; } - public function hasPaymentProcess() : bool + public function hasPaymentProcess(): bool { return $this->conference->getMeta('payment.enabled') && match ($this->status) { SubmissionStatus::OnReview, SubmissionStatus::Editing, SubmissionStatus::Published => true, diff --git a/app/Panel/Livewire/Submissions/CallforAbstract.php b/app/Panel/Livewire/Submissions/CallforAbstract.php index 5b71235e4..994b05db2 100644 --- a/app/Panel/Livewire/Submissions/CallforAbstract.php +++ b/app/Panel/Livewire/Submissions/CallforAbstract.php @@ -2,11 +2,8 @@ namespace App\Panel\Livewire\Submissions; -use App\Actions\Submissions\SubmissionUpdateAction; use App\Mail\Templates\AcceptAbstractMail; use App\Mail\Templates\DeclineAbstractMail; -use App\Models\Enums\SubmissionStage; -use App\Models\Enums\SubmissionStatus; use App\Models\MailTemplate; use App\Models\Submission; use App\Notifications\AbstractAccepted; @@ -176,11 +173,11 @@ function (Action $action, array $data) { ) ); - $action->successRedirectUrl( - SubmissionResource::getUrl('view', [ - 'record' => $this->submission->getKey(), - ]) - ); + $action->successRedirectUrl( + SubmissionResource::getUrl('view', [ + 'record' => $this->submission->getKey(), + ]) + ); $action->success(); } catch (\Throwable $th) { diff --git a/app/Panel/Livewire/Submissions/Forms/Publish.php b/app/Panel/Livewire/Submissions/Forms/Publish.php index 69ad78d84..eebacc009 100644 --- a/app/Panel/Livewire/Submissions/Forms/Publish.php +++ b/app/Panel/Livewire/Submissions/Forms/Publish.php @@ -2,7 +2,6 @@ namespace App\Panel\Livewire\Submissions\Forms; -use App\Actions\Submissions\SubmissionUpdateAction; use App\Mail\Templates\PublishSubmissionMail; use App\Models\Enums\SubmissionStage; use App\Models\Enums\SubmissionStatus; @@ -24,7 +23,6 @@ use Filament\Infolists\Concerns\InteractsWithInfolists; use Filament\Infolists\Contracts\HasInfolists; use Filament\Infolists\Infolist; -use HTML5; use Illuminate\Support\Facades\Mail; use Illuminate\Support\HtmlString; use Mohamedsabil83\FilamentFormsTinyeditor\Components\TinyEditor; @@ -36,7 +34,7 @@ class Publish extends \Livewire\Component implements HasActions, HasForms, HasIn public Submission $submission; public function handlePublishAction(Action $action, array $data) - { + { $this->submission->state()->publish(); if (! $data['do-not-notify-author']) { @@ -79,9 +77,9 @@ public function publishAction() ->icon('iconpark-check') ->label('Send to Proceeding') ->when( - fn() => $this->submission->hasPaymentProcess() && !$this->submission->payment?->isCompleted(), + fn () => $this->submission->hasPaymentProcess() && ! $this->submission->payment?->isCompleted(), fn (Action $action): Action => $action - ->modalContent(new HtmlString(<<modalContent(new HtmlString(<<<'HTML'

Submission fee has not been paid, please notify the author.

HTML)) ->modalWidth('xl') @@ -89,33 +87,33 @@ public function publishAction() ) ->when( // true, - fn() => !$this->submission->hasPaymentProcess() || $this->submission->payment?->isCompleted(), + fn () => ! $this->submission->hasPaymentProcess() || $this->submission->payment?->isCompleted(), fn (Action $action): Action => $action - ->successNotificationTitle('Submission published successfully') - ->mountUsing(function (Form $form) { - $mailTemplate = MailTemplate::where('mailable', PublishSubmissionMail::class)->first(); - $form->fill([ - 'email' => $this->submission->user->email, - 'subject' => $mailTemplate ? $mailTemplate->subject : '', - 'message' => $mailTemplate ? $mailTemplate->html_template : '', - ]); - }) - ->form([ - Fieldset::make('Notification') - ->columns(1) - ->schema([ - TextInput::make('email') - ->disabled() - ->dehydrated(), - TextInput::make('subject') - ->required(), - TinyEditor::make('message') - ->minHeight(300), - Checkbox::make('do-not-notify-author') - ->label("Don't Send Notification to Author"), - ]), - ]) - ->action(fn (Action $action, array $data) => $this->handlePublishAction($action, $data)) + ->successNotificationTitle('Submission published successfully') + ->mountUsing(function (Form $form) { + $mailTemplate = MailTemplate::where('mailable', PublishSubmissionMail::class)->first(); + $form->fill([ + 'email' => $this->submission->user->email, + 'subject' => $mailTemplate ? $mailTemplate->subject : '', + 'message' => $mailTemplate ? $mailTemplate->html_template : '', + ]); + }) + ->form([ + Fieldset::make('Notification') + ->columns(1) + ->schema([ + TextInput::make('email') + ->disabled() + ->dehydrated(), + TextInput::make('subject') + ->required(), + TinyEditor::make('message') + ->minHeight(300), + Checkbox::make('do-not-notify-author') + ->label("Don't Send Notification to Author"), + ]), + ]) + ->action(fn (Action $action, array $data) => $this->handlePublishAction($action, $data)) ); } diff --git a/app/Panel/Livewire/Submissions/Payment.php b/app/Panel/Livewire/Submissions/Payment.php index 5569e17e9..cc0c33d68 100644 --- a/app/Panel/Livewire/Submissions/Payment.php +++ b/app/Panel/Livewire/Submissions/Payment.php @@ -3,9 +3,8 @@ namespace App\Panel\Livewire\Submissions; use App\Facades\Payment as PaymentFacade; -use App\Models\Conference; -use App\Models\Submission; use App\Models\PaymentItem; +use App\Models\Submission; use App\Panel\Livewire\Workflows\Classes\StageManager; use App\Panel\Livewire\Workflows\Concerns\InteractWithTenant; use Filament\Actions\Concerns\InteractsWithActions; @@ -55,7 +54,7 @@ public function form(Form $form) Currency::query() ->whereIn('id', App::getCurrentConference()->getSupportedCurrencies()) ->get() - ->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name . ' (' . $currency->symbol_native . ')']) + ->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name.' ('.$currency->symbol_native.')']) ) ->required() ->reactive(), @@ -63,17 +62,21 @@ public function form(Form $form) ->visible(fn (Get $get) => $get('currency_id')) ->options(function (Get $get) { return PaymentItem::get() - ->filter(function (PaymentItem $item) use ($get) : bool { + ->filter(function (PaymentItem $item) use ($get): bool { foreach ($item->fees as $fee) { - if(!array_key_exists('currency_id', $fee)) continue; - if($fee['currency_id'] === $get('currency_id')) return true; + if (! array_key_exists('currency_id', $fee)) { + continue; + } + if ($fee['currency_id'] === $get('currency_id')) { + return true; + } } return false; }) - ->map(fn (PaymentItem $item) : string => $item->name . ': ' . $item->getAmount($get('currency_id'))); + ->map(fn (PaymentItem $item): string => $item->name.': '.$item->getAmount($get('currency_id'))); }), - ]) + ]), ]); } } diff --git a/app/Panel/Livewire/Workflows/PaymentSetting.php b/app/Panel/Livewire/Workflows/PaymentSetting.php index d3f1c2a64..38152d80d 100644 --- a/app/Panel/Livewire/Workflows/PaymentSetting.php +++ b/app/Panel/Livewire/Workflows/PaymentSetting.php @@ -4,7 +4,6 @@ use App\Facades\Payment; use App\Panel\Livewire\Workflows\Base\WorkflowStage; -use Awcodes\Shout\Components\Shout; use Filament\Actions\Action; use Filament\Actions\Concerns\InteractsWithActions; use Filament\Actions\Contracts\HasActions; @@ -15,7 +14,6 @@ use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; use Filament\Forms\Get; -use Illuminate\Support\Arr; use Illuminate\Support\Facades\Log; use Squire\Models\Currency; @@ -31,13 +29,13 @@ class PaymentSetting extends WorkflowStage implements HasActions, HasForms public function mount() { - $this->form->fill([ + $this->form->fill([ 'payment' => [ 'enabled' => $this->conference->getMeta('payment.enabled'), 'method' => $this->conference->getMeta('payment.method', 'manual'), 'supported_currencies' => $this->conference->getMeta('payment.supported_currencies', ['usd']), ], - ...Payment::getAllDriverNames()->map(fn ($name, $key) => Payment::driver($key)->getSettingFormFill())->toArray(), + ...Payment::getAllDriverNames()->map(fn ($name, $key) => Payment::driver($key)?->getSettingFormFill() ?? [])->toArray(), ]); } @@ -53,15 +51,15 @@ public function submitAction() try { $data = $this->form->getState(); - + foreach ($data['payment'] as $key => $value) { - $this->conference->setMeta('payment.' . $key, $value); + $this->conference->setMeta('payment.'.$key, $value); } Payment::driver($this->conference->getMeta('payment.method')) ->saveSetting(data_get($data, $this->conference->getMeta('payment.method'), [])); } catch (\Throwable $th) { - + Log::error($th); $action->failure(); @@ -94,9 +92,9 @@ public function form(Form $form): Form ->options(Currency::query()->get()->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name.' ('.$currency->symbol_native.')'])->toArray()) ->optionsLimit(250), Grid::make(1) - ->hidden(fn (Get $get) => !$get('payment.method')) - ->schema(fn (Get $get) => Payment::driver($get('payment.method'))->getSettingFormSchema()), - ]) + ->hidden(fn (Get $get) => ! $get('payment.method')) + ->schema(fn (Get $get) => Payment::driver($get('payment.method'))?->getSettingFormSchema() ?? []), + ]), ]); } diff --git a/app/Panel/Pages/Settings/Workflow.php b/app/Panel/Pages/Settings/Workflow.php index 07538a72a..74398bbd8 100644 --- a/app/Panel/Pages/Settings/Workflow.php +++ b/app/Panel/Pages/Settings/Workflow.php @@ -35,7 +35,7 @@ class Workflow extends Page implements HasForms, HasInfolists public function booted(): void { - abort_if(!static::canView(), 403); + abort_if(! static::canView(), 403); } public static function shouldRegisterNavigation(): bool diff --git a/app/Panel/Resources/SubmissionResource/Pages/ManageSubmissions.php b/app/Panel/Resources/SubmissionResource/Pages/ManageSubmissions.php index 5e4bcb2ad..17fcab865 100644 --- a/app/Panel/Resources/SubmissionResource/Pages/ManageSubmissions.php +++ b/app/Panel/Resources/SubmissionResource/Pages/ManageSubmissions.php @@ -16,7 +16,6 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Support\HtmlString; - class ManageSubmissions extends ManageRecords { protected static string $resource = SubmissionResource::class; diff --git a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php index 1e7ed8834..3490b2acd 100644 --- a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php +++ b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php @@ -5,7 +5,6 @@ use App\Actions\Submissions\AcceptWithdrawalAction; use App\Actions\Submissions\CancelWithdrawalAction; use App\Actions\Submissions\RequestWithdrawalAction; -use App\Actions\Submissions\UnpublishSubmissionAction; use App\Facades\Payment as FacadesPayment; use App\Infolists\Components\LivewireEntry; use App\Infolists\Components\VerticalTabs\Tab as Tab; @@ -34,7 +33,6 @@ use Filament\Actions\StaticAction; use Filament\Forms\Components\CheckboxList; use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Radio; use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; @@ -83,7 +81,7 @@ protected function getHeaderActions(): array ->color('primary') ->modalHeading('Submission Payment') ->when( - fn (Action $action): bool => !$action->getRecord() || $action->getRecord()?->state->isOneOf(PaymentState::Unpaid), + fn (Action $action): bool => ! $action->getRecord() || $action->getRecord()?->state->isOneOf(PaymentState::Unpaid), fn (Action $action): Action => $action ->action(function (array $data, Form $form) { @@ -99,7 +97,6 @@ protected function getHeaderActions(): array FacadesPayment::driver($this->record->payment?->payment_method)->handlePayment($payment); })->mountUsing(function (Form $form) { $payment = $this->record->payment; - $form->fill([ 'currency_id' => $payment?->currency_id, ...FacadesPayment::getPaymentFormFill(), @@ -111,7 +108,7 @@ protected function getHeaderActions(): array Currency::query() ->whereIn('id', App::getCurrentConference()->getSupportedCurrencies()) ->get() - ->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name . ' (' . $currency->symbol_native . ')']) + ->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name.' ('.$currency->symbol_native.')']) ) ->required() ->reactive(), @@ -122,14 +119,18 @@ protected function getHeaderActions(): array return PaymentItem::get() ->filter(function (PaymentItem $item) use ($get): bool { foreach ($item->fees as $fee) { - if (!array_key_exists('currency_id', $fee)) continue; - if ($fee['currency_id'] === $get('currency_id')) return true; + if (! array_key_exists('currency_id', $fee)) { + continue; + } + if ($fee['currency_id'] === $get('currency_id')) { + return true; + } } return false; }) // ->mapWithKeys(fn (PaymentItem $item): array => [$item->getAmount($get('currency_id')) => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); - ->mapWithKeys(fn (PaymentItem $item): array => [$item->id => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); + ->mapWithKeys(fn (PaymentItem $item): array => [$item->id => $item->name.': '.$item->getFormattedAmount($get('currency_id'))]); }), ...FacadesPayment::driver($this->record->payment?->payment_method)->getPaymentFormSchema(), ]), @@ -141,16 +142,16 @@ protected function getHeaderActions(): array $record->state = $data['decision']; $record->save(); }) - ->modalSubmitAction(fn(StaticAction $action) => $action->hidden($this->record->payment?->isCompleted())) - ->modalCancelAction(fn(StaticAction $action) => $action->hidden($this->record->payment?->isCompleted())) + ->modalSubmitAction(fn (StaticAction $action) => $action->hidden($this->record->payment?->isCompleted())) + ->modalCancelAction(fn (StaticAction $action) => $action->hidden($this->record->payment?->isCompleted())) ->mountUsing(function (Form $form) { $payment = $this->record->payment; $form->fill([ 'currency_id' => $payment?->currency_id, - 'amount' => $payment?->amount, - 'items' => array_keys($payment?->getMeta('items') ?? []), - ...FacadesPayment::getPaymentFormFill(), + 'amount' => $payment?->amount, + 'items' => array_keys($payment?->getMeta('items') ?? []), + ...FacadesPayment::driver($payment?->payment_method)?->getPaymentFormFill() ?? [], ]); }) ->form([ @@ -168,12 +169,12 @@ protected function getHeaderActions(): array CheckboxList::make('items') ->options($this->record->payment?->getMeta('items')), - ...FacadesPayment::driver($this->record->payment?->payment_method)->getPaymentFormSchema(), + ...FacadesPayment::driver($this->record->payment?->payment_method)?->getPaymentFormSchema() ?? [], ]) ->disabled(), Select::make('decision') ->required() - ->hidden(fn() => $this->record->payment?->isCompleted()) + ->hidden(fn () => $this->record->payment?->isCompleted()) ->options([ PaymentState::Unpaid->value => PaymentState::Unpaid->name, PaymentState::Waived->value => PaymentState::Waived->name, @@ -253,7 +254,7 @@ protected function getHeaderActions(): array ->color('danger') ->extraAttributes(function (Action $action) { if (filled($this->record->withdrawn_reason)) { - $attributeValue = '$nextTick(() => { $wire.mountAction(\'' . $action->getName() . '\') })'; + $attributeValue = '$nextTick(() => { $wire.mountAction(\''.$action->getName().'\') })'; return [ 'x-init' => new HtmlString($attributeValue), @@ -277,7 +278,7 @@ protected function getHeaderActions(): array ]) ->requiresConfirmation() ->modalHeading(function () { - return $this->record->user->fullName . ' has requested to withdraw this submission.'; + return $this->record->user->fullName.' has requested to withdraw this submission.'; }) ->modalDescription("You can either reject the request or accept it, remember it can't be undone.") ->modalCancelActionLabel('Ignore') @@ -324,13 +325,13 @@ public function getSubheading(): string|Htmlable|null $badgeHtml = '
'; $badgeHtml .= match ($this->record->status) { - SubmissionStatus::Incomplete => '' . SubmissionStatus::Incomplete->value . '', - SubmissionStatus::Queued => '' . SubmissionStatus::Queued->value . '', - SubmissionStatus::OnReview => '' . SubmissionStatus::OnReview->value . '', - SubmissionStatus::Published => '' . SubmissionStatus::Published->value . '', - SubmissionStatus::Editing => '' . SubmissionStatus::Editing->value . '', - SubmissionStatus::Declined => '' . SubmissionStatus::Declined->value . '', - SubmissionStatus::Withdrawn => '' . SubmissionStatus::Withdrawn->value . '', + SubmissionStatus::Incomplete => ''.SubmissionStatus::Incomplete->value.'', + SubmissionStatus::Queued => ''.SubmissionStatus::Queued->value.'', + SubmissionStatus::OnReview => ''.SubmissionStatus::OnReview->value.'', + SubmissionStatus::Published => ''.SubmissionStatus::Published->value.'', + SubmissionStatus::Editing => ''.SubmissionStatus::Editing->value.'', + SubmissionStatus::Declined => ''.SubmissionStatus::Declined->value.'', + SubmissionStatus::Withdrawn => ''.SubmissionStatus::Withdrawn->value.'', default => null, }; @@ -381,7 +382,7 @@ public function infolist(Infolist $infolist): Infolist Tab::make('Call for Abstract') ->icon('heroicon-o-information-circle') ->schema(function () { - if (!StageManager::callForAbstract()->isStageOpen() && !$this->record->isPublished()) { + if (! StageManager::callForAbstract()->isStageOpen() && ! $this->record->isPublished()) { return [ ShoutEntry::make('call-for-abstract-closed') ->type('warning') @@ -400,7 +401,7 @@ public function infolist(Infolist $infolist): Infolist Tab::make('Peer Review') ->icon('iconpark-checklist-o') ->schema(function (): array { - if (!StageManager::peerReview()->isStageOpen() && !$this->record->isPublished()) { + if (! StageManager::peerReview()->isStageOpen() && ! $this->record->isPublished()) { return [ ShoutEntry::make('peer-review-closed') ->type('warning') @@ -419,7 +420,7 @@ public function infolist(Infolist $infolist): Infolist Tab::make('Editing') ->icon('heroicon-o-pencil') ->schema(function () { - if (!StageManager::editing()->isStageOpen() && !$this->record->isPublished()) { + if (! StageManager::editing()->isStageOpen() && ! $this->record->isPublished()) { return [ ShoutEntry::make('editing-closed') ->type('warning') @@ -467,7 +468,7 @@ public function infolist(Infolist $infolist): Infolist LivewireEntry::make('contributors') ->livewire(ContributorList::class, [ 'submission' => $this->record, - 'viewOnly' => !auth()->user()->can('editing', $this->record), + 'viewOnly' => ! auth()->user()->can('editing', $this->record), ]), ]), Tab::make('References') diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 914a84d13..27418748e 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,8 +2,10 @@ namespace App\Providers; +use App\Facades\Payment; use App\Managers\BlockManager; use App\Managers\MetaTagManager; +use App\Services\Payments\PaypalPayment; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Facades\DB; @@ -37,6 +39,10 @@ public function boot(): void $this->setupModel(); $this->setupStorage(); $this->extendStr(); + + // Payment::extend('paypal', function () { + // return new PaypalPayment; + // }); } protected function extendStr() diff --git a/app/Services/Payments/ManualPayment.php b/app/Services/Payments/ManualPayment.php index 861f4b6c7..0999b5039 100644 --- a/app/Services/Payments/ManualPayment.php +++ b/app/Services/Payments/ManualPayment.php @@ -4,10 +4,7 @@ use App\Models\Enums\PaymentState; use App\Models\Payment; -use Filament\Forms\Components\Section; use Filament\Forms\Components\SpatieMediaLibraryFileUpload; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; use Illuminate\Support\Facades\App; use Mohamedsabil83\FilamentFormsTinyeditor\Components\TinyEditor; @@ -18,19 +15,10 @@ public function getName(): string return 'Manual Payment'; } - public function pay($amount, $submission) - { - $submission->update([ - 'payment_amount' => $amount, - 'payment_status' => 'paid', - ]); - } - public function handlePayment(Payment $payment) { // Send information to Editor that user is paying the submission - // Change payment status to processing $payment->state = PaymentState::Processing; $payment->save(); diff --git a/app/Services/Payments/PaypalPayment.php b/app/Services/Payments/PaypalPayment.php new file mode 100644 index 000000000..15aa63f2f --- /dev/null +++ b/app/Services/Payments/PaypalPayment.php @@ -0,0 +1,48 @@ +state = PaymentState::Paid; + $payment->paid_at = now(); + $payment->save(); + } + + public function getPaymentFormSchema(): array + { + return []; + } + + public function getPaymentFormFill(): array + { + return []; + } + + public function getSettingFormSchema(): array + { + return []; + } + + public function getSettingFormFill(): array + { + return []; + } + + public function saveSetting(array $data): void + { + } +} From 2c0db2b0fd48196cb27ea5f82c9e5b5cf9c59ff2 Mon Sep 17 00:00:00 2001 From: Rahman Ramsi Date: Thu, 21 Dec 2023 09:11:06 +0800 Subject: [PATCH 8/9] Add PaymentPolicy --- app/Policies/PaymentPolicy.php | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 app/Policies/PaymentPolicy.php diff --git a/app/Policies/PaymentPolicy.php b/app/Policies/PaymentPolicy.php new file mode 100644 index 000000000..a17704b99 --- /dev/null +++ b/app/Policies/PaymentPolicy.php @@ -0,0 +1,32 @@ +isCompleted()){ + return false; + } + + if($user->can('Payment:update')){ + return true; + } + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Payment $payment) + { + return false; + } +} From a2796a5631c3a4a2a1db81e768b3a5ff300c7778 Mon Sep 17 00:00:00 2001 From: Rahman Ramsi Date: Thu, 21 Dec 2023 09:11:38 +0800 Subject: [PATCH 9/9] fix condition --- .../Livewire/Submissions/Forms/Publish.php | 1 - .../Pages/ViewSubmission.php | 148 +++++++++++------- 2 files changed, 92 insertions(+), 57 deletions(-) diff --git a/app/Panel/Livewire/Submissions/Forms/Publish.php b/app/Panel/Livewire/Submissions/Forms/Publish.php index eebacc009..9e3524558 100644 --- a/app/Panel/Livewire/Submissions/Forms/Publish.php +++ b/app/Panel/Livewire/Submissions/Forms/Publish.php @@ -86,7 +86,6 @@ public function publishAction() ->modalSubmitAction(false) ) ->when( - // true, fn () => ! $this->submission->hasPaymentProcess() || $this->submission->payment?->isCompleted(), fn (Action $action): Action => $action ->successNotificationTitle('Submission published successfully') diff --git a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php index 3490b2acd..b33159997 100644 --- a/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php +++ b/app/Panel/Resources/SubmissionResource/Pages/ViewSubmission.php @@ -13,6 +13,7 @@ use App\Models\Enums\SubmissionStage; use App\Models\Enums\SubmissionStatus; use App\Models\Enums\UserRole; +use App\Models\Payment; use App\Models\PaymentItem; use App\Models\User; use App\Notifications\SubmissionWithdrawn; @@ -23,7 +24,6 @@ use App\Panel\Livewire\Submissions\Forms\Detail; use App\Panel\Livewire\Submissions\Forms\Publish; use App\Panel\Livewire\Submissions\Forms\References; -use App\Panel\Livewire\Submissions\Payment; use App\Panel\Livewire\Submissions\PeerReview; use App\Panel\Livewire\Workflows\Classes\StageManager; use App\Panel\Livewire\Workflows\Concerns\InteractWithTenant; @@ -70,6 +70,21 @@ public function mount($record): void abort_unless(static::getResource()::canView($this->getRecord()), 403); } + /** + * @return array + */ + public function getBreadcrumbs(): array + { + $resource = static::getResource(); + + $breadcrumb = $this->getBreadcrumb(); + + return [ + $resource::getUrl() => $resource::getBreadcrumb(), + ...(filled($breadcrumb) ? [$breadcrumb] : []), + ]; + } + protected function getHeaderActions(): array { return [ @@ -81,7 +96,18 @@ protected function getHeaderActions(): array ->color('primary') ->modalHeading('Submission Payment') ->when( - fn (Action $action): bool => ! $action->getRecord() || $action->getRecord()?->state->isOneOf(PaymentState::Unpaid), + fn (Action $action) => !FacadesPayment::driver($action->getRecord()?->payment_method), + fn (Action $action) => $action + ->modalContent(function($action){ + $paymentMethod = $action->getRecord()?->payment_method ?? FacadesPayment::getDefaultDriver(); + + return new HtmlString("

There's a problem with configured payment method. Please contact administrator.
Payment method : " . $paymentMethod . "

"); + }) + ->modalWidth('xl') + ->modalSubmitAction(false), + ) + ->when( + fn (Action $action): bool => FacadesPayment::driver() && (!$action->getRecord() || $action->getRecord()?->state->isOneOf(PaymentState::Unpaid) && FacadesPayment::driver()), fn (Action $action): Action => $action ->action(function (array $data, Form $form) { @@ -94,56 +120,64 @@ protected function getHeaderActions(): array $form->model($payment)->saveRelationships(); - FacadesPayment::driver($this->record->payment?->payment_method)->handlePayment($payment); - })->mountUsing(function (Form $form) { - $payment = $this->record->payment; + $paymentDriver = FacadesPayment::driver($payment?->payment_method); + + $paymentDriver->handlePayment($payment); + })->mountUsing(function (Form $form, ?Payment $record) { + + $paymentDriver = FacadesPayment::driver($record?->payment_method); $form->fill([ - 'currency_id' => $payment?->currency_id, - ...FacadesPayment::getPaymentFormFill(), + 'currency_id' => $record?->currency_id, + ...$paymentDriver->getPaymentFormFill(), ]); - })->form([ - Select::make('currency_id') - ->label('Currency') - ->options( - Currency::query() - ->whereIn('id', App::getCurrentConference()->getSupportedCurrencies()) - ->get() - ->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name.' ('.$currency->symbol_native.')']) - ) - ->required() - ->reactive(), - CheckboxList::make('items') - ->visible(fn (Get $get) => $get('currency_id')) - ->required() - ->options(function (Get $get) { - return PaymentItem::get() - ->filter(function (PaymentItem $item) use ($get): bool { - foreach ($item->fees as $fee) { - if (! array_key_exists('currency_id', $fee)) { - continue; - } - if ($fee['currency_id'] === $get('currency_id')) { - return true; + })->form(function (?Payment $record) { + + $paymentDriver = FacadesPayment::driver($record?->payment_method); + + return [ + Select::make('currency_id') + ->label('Currency') + ->options( + Currency::query() + ->whereIn('id', App::getCurrentConference()->getSupportedCurrencies()) + ->get() + ->mapWithKeys(fn (Currency $currency) => [$currency->id => $currency->name . ' (' . $currency->symbol_native . ')']) + ) + ->required() + ->reactive(), + CheckboxList::make('items') + ->visible(fn (Get $get) => $get('currency_id')) + ->required() + ->options(function (Get $get) { + return PaymentItem::get() + ->filter(function (PaymentItem $item) use ($get): bool { + foreach ($item->fees as $fee) { + if (!array_key_exists('currency_id', $fee)) { + continue; + } + if ($fee['currency_id'] === $get('currency_id')) { + return true; + } } - } - - return false; - }) - // ->mapWithKeys(fn (PaymentItem $item): array => [$item->getAmount($get('currency_id')) => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); - ->mapWithKeys(fn (PaymentItem $item): array => [$item->id => $item->name.': '.$item->getFormattedAmount($get('currency_id'))]); - }), - ...FacadesPayment::driver($this->record->payment?->payment_method)->getPaymentFormSchema(), - ]), + + return false; + }) + // ->mapWithKeys(fn (PaymentItem $item): array => [$item->getAmount($get('currency_id')) => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); + ->mapWithKeys(fn (PaymentItem $item): array => [$item->id => $item->name . ': ' . $item->getFormattedAmount($get('currency_id'))]); + }), + ...$paymentDriver->getPaymentFormSchema() ?? [], + ]; + }), ) ->when( - fn (Action $action): bool => $action->getRecord()?->state->isOneOf(PaymentState::Processing, PaymentState::Paid, PaymentState::Waived) ?? false, + fn (Action $action): bool => FacadesPayment::driver($action->getRecord()?->payment_method) && $action->getRecord()?->state->isOneOf(PaymentState::Processing, PaymentState::Paid, PaymentState::Waived), fn (Action $action): Action => $action ->action(function (array $data, $record) { $record->state = $data['decision']; $record->save(); }) - ->modalSubmitAction(fn (StaticAction $action) => $action->hidden($this->record->payment?->isCompleted())) - ->modalCancelAction(fn (StaticAction $action) => $action->hidden($this->record->payment?->isCompleted())) + ->modalSubmitAction(fn (StaticAction $action, ?Payment $record) => $action->visible(auth()->user()->can('update', $record))) + ->modalCancelAction(fn (StaticAction $action, ?Payment $record) => $action->visible(auth()->user()->can('update', $record))) ->mountUsing(function (Form $form) { $payment = $this->record->payment; @@ -153,6 +187,8 @@ protected function getHeaderActions(): array 'items' => array_keys($payment?->getMeta('items') ?? []), ...FacadesPayment::driver($payment?->payment_method)?->getPaymentFormFill() ?? [], ]); + + $form->disabled(fn ($record) => !auth()->user()->can('update', $record)); }) ->form([ Grid::make(1) @@ -174,7 +210,7 @@ protected function getHeaderActions(): array ->disabled(), Select::make('decision') ->required() - ->hidden(fn () => $this->record->payment?->isCompleted()) + ->visible(fn ($record) => auth()->user()->can('update', $record)) ->options([ PaymentState::Unpaid->value => PaymentState::Unpaid->name, PaymentState::Waived->value => PaymentState::Waived->name, @@ -254,7 +290,7 @@ protected function getHeaderActions(): array ->color('danger') ->extraAttributes(function (Action $action) { if (filled($this->record->withdrawn_reason)) { - $attributeValue = '$nextTick(() => { $wire.mountAction(\''.$action->getName().'\') })'; + $attributeValue = '$nextTick(() => { $wire.mountAction(\'' . $action->getName() . '\') })'; return [ 'x-init' => new HtmlString($attributeValue), @@ -278,7 +314,7 @@ protected function getHeaderActions(): array ]) ->requiresConfirmation() ->modalHeading(function () { - return $this->record->user->fullName.' has requested to withdraw this submission.'; + return $this->record->user->fullName . ' has requested to withdraw this submission.'; }) ->modalDescription("You can either reject the request or accept it, remember it can't be undone.") ->modalCancelActionLabel('Ignore') @@ -325,13 +361,13 @@ public function getSubheading(): string|Htmlable|null $badgeHtml = '
'; $badgeHtml .= match ($this->record->status) { - SubmissionStatus::Incomplete => ''.SubmissionStatus::Incomplete->value.'', - SubmissionStatus::Queued => ''.SubmissionStatus::Queued->value.'', - SubmissionStatus::OnReview => ''.SubmissionStatus::OnReview->value.'', - SubmissionStatus::Published => ''.SubmissionStatus::Published->value.'', - SubmissionStatus::Editing => ''.SubmissionStatus::Editing->value.'', - SubmissionStatus::Declined => ''.SubmissionStatus::Declined->value.'', - SubmissionStatus::Withdrawn => ''.SubmissionStatus::Withdrawn->value.'', + SubmissionStatus::Incomplete => '' . SubmissionStatus::Incomplete->value . '', + SubmissionStatus::Queued => '' . SubmissionStatus::Queued->value . '', + SubmissionStatus::OnReview => '' . SubmissionStatus::OnReview->value . '', + SubmissionStatus::Published => '' . SubmissionStatus::Published->value . '', + SubmissionStatus::Editing => '' . SubmissionStatus::Editing->value . '', + SubmissionStatus::Declined => '' . SubmissionStatus::Declined->value . '', + SubmissionStatus::Withdrawn => '' . SubmissionStatus::Withdrawn->value . '', default => null, }; @@ -382,7 +418,7 @@ public function infolist(Infolist $infolist): Infolist Tab::make('Call for Abstract') ->icon('heroicon-o-information-circle') ->schema(function () { - if (! StageManager::callForAbstract()->isStageOpen() && ! $this->record->isPublished()) { + if (!StageManager::callForAbstract()->isStageOpen() && !$this->record->isPublished()) { return [ ShoutEntry::make('call-for-abstract-closed') ->type('warning') @@ -401,7 +437,7 @@ public function infolist(Infolist $infolist): Infolist Tab::make('Peer Review') ->icon('iconpark-checklist-o') ->schema(function (): array { - if (! StageManager::peerReview()->isStageOpen() && ! $this->record->isPublished()) { + if (!StageManager::peerReview()->isStageOpen() && !$this->record->isPublished()) { return [ ShoutEntry::make('peer-review-closed') ->type('warning') @@ -420,7 +456,7 @@ public function infolist(Infolist $infolist): Infolist Tab::make('Editing') ->icon('heroicon-o-pencil') ->schema(function () { - if (! StageManager::editing()->isStageOpen() && ! $this->record->isPublished()) { + if (!StageManager::editing()->isStageOpen() && !$this->record->isPublished()) { return [ ShoutEntry::make('editing-closed') ->type('warning') @@ -468,7 +504,7 @@ public function infolist(Infolist $infolist): Infolist LivewireEntry::make('contributors') ->livewire(ContributorList::class, [ 'submission' => $this->record, - 'viewOnly' => ! auth()->user()->can('editing', $this->record), + 'viewOnly' => !auth()->user()->can('editing', $this->record), ]), ]), Tab::make('References')