new payment flow

This commit is contained in:
David Bomba 2024-07-02 14:54:50 +10:00 committed by Benjamin Beganović
parent caeed4456b
commit ae2bf51028
8 changed files with 94 additions and 28 deletions

View File

@ -26,7 +26,7 @@ class PaymentMethod extends Component
public $methods = []; public $methods = [];
public $isLoading = true; public $isLoading = false;
public $amount = 0; public $amount = 0;

View File

@ -30,18 +30,6 @@ class ProcessPayment extends Component
public $isLoading = true; public $isLoading = true;
private string $component_view = '';
private array $payment_data_payload = [];
public $isLoading = true;
// public function toJSON()
// {
// nlog("why");
// }
public function mount() public function mount()
{ {
@ -71,12 +59,12 @@ class ProcessPayment extends Component
} }
$driver = $company_gateway $driver = $company_gateway
->driver($invitation->contact->client) // @phpstan-ignore-line ->driver($invitation->contact->client)
->setPaymentMethod($data['payment_method_id']) ->setPaymentMethod($data['payment_method_id'])
->setPaymentHash($responder_data['payload']['ph']); ->setPaymentHash($responder_data['payload']['ph']);
$this->payment_data_payload = $driver->processPaymentViewData($responder_data['payload']); $this->payment_data_payload = $driver->processPaymentViewData($responder_data['payload']);
$this->payment_view = $driver->livewirePaymentView( $this->payment_view = $driver->livewirePaymentView(
$this->payment_data_payload, $this->payment_data_payload,
); );
@ -95,4 +83,4 @@ class ProcessPayment extends Component
return render($this->payment_view, $this->payment_data_payload); return render($this->payment_view, $this->payment_data_payload);
} }
} }

View File

@ -88,7 +88,7 @@ class RequiredFields extends Component
$rff = new RFFService( $rff = new RFFService(
fields: $this->getContext()['fields'], fields: $this->getContext()['fields'],
database: $this->getContext()['db'], database: $this->getContext()['db'],
company_gateway_id: (string)$this->company_gateway->id, company_gateway_id: $this->company_gateway->id,
); );
/** @var \App\Models\ClientContact $contact */ /** @var \App\Models\ClientContact $contact */
@ -111,7 +111,7 @@ class RequiredFields extends Component
$rff = new RFFService( $rff = new RFFService(
fields: $this->fields, fields: $this->fields,
database: $this->getContext()['db'], database: $this->getContext()['db'],
company_gateway_id: (string) $this->company_gateway->id, company_gateway_id: $this->company_gateway->id,
); );
$contact = auth()->user(); $contact = auth()->user();
@ -133,4 +133,4 @@ class RequiredFields extends Component
'contact' => $this->getContext()['contact'], 'contact' => $this->getContext()['contact'],
]); ]);
} }
} }

View File

@ -18,6 +18,7 @@ use Livewire\Component;
class UnderOverPayment extends Component class UnderOverPayment extends Component
{ {
use WithSecureContext; use WithSecureContext;
public $payableAmount; public $payableAmount;
@ -44,28 +45,29 @@ class UnderOverPayment extends Component
$settings = $this->getContext()['settings']; $settings = $this->getContext()['settings'];
foreach($payableInvoices as $key => $invoice) { foreach($payableInvoices as $key => $invoice){
$payableInvoices[$key]['amount'] = Number::parseFloat($invoice['formatted_amount']); $payableInvoices[$key]['amount'] = Number::parseFloat($invoice['formatted_amount']);
} }
$input_amount = collect($payableInvoices)->sum('amount'); $input_amount = collect($payableInvoices)->sum('amount');
if($settings->client_portal_allow_under_payment && $settings->client_portal_under_payment_minimum != 0) { if($settings->client_portal_allow_under_payment && $settings->client_portal_under_payment_minimum != 0)
if($input_amount <= $settings->client_portal_under_payment_minimum) { {
if($input_amount <= $settings->client_portal_under_payment_minimum){
// return error message under payment too low. // return error message under payment too low.
$this->errors = ctrans('texts.minimum_required_payment', ['amount' => $settings->client_portal_under_payment_minimum]); $this->errors = ctrans('texts.minimum_required_payment', ['amount' => $settings->client_portal_under_payment_minimum]);
$this->dispatch('errorMessageUpdate', errors: $this->errors); $this->dispatch('errorMessageUpdate', errors: $this->errors);
} }
} }
if(!$settings->client_portal_allow_over_payment && ($input_amount > $this->invoice_amount)) { if(!$settings->client_portal_allow_over_payment && ($input_amount > $this->invoice_amount)){
$this->errors = ctrans('texts.over_payments_disabled'); $this->errors = ctrans('texts.over_payments_disabled');
$this->dispatch('errorMessageUpdate', errors: $this->errors); $this->dispatch('errorMessageUpdate', errors: $this->errors);
} }
if(!$this->errors) { if(!$this->errors){
$this->setContext('payable_invoices', $payableInvoices); $this->setContext('payable_invoices', $payableInvoices);
$this->dispatch('payable-amount', payable_amount: $input_amount); $this->dispatch('payable-amount', payable_amount: $input_amount );
} }
} }
@ -73,4 +75,4 @@ class UnderOverPayment extends Component
{ {
return render('flow2.under-over-payments'); return render('flow2.under-over-payments');
} }
} }

View File

@ -22,6 +22,8 @@ use Livewire\Attributes\Computed;
use Livewire\Attributes\Reactive; use Livewire\Attributes\Reactive;
use App\Livewire\Flow2\PaymentMethod; use App\Livewire\Flow2\PaymentMethod;
use App\Livewire\Flow2\ProcessPayment; use App\Livewire\Flow2\ProcessPayment;
use App\Livewire\Flow2\UnderOverPayment;
use App\Utils\Number;
class InvoicePay extends Component class InvoicePay extends Component
{ {
@ -37,6 +39,12 @@ class InvoicePay extends Component
public $payment_method_accepted = false; public $payment_method_accepted = false;
public $under_over_payment = false;
public $required_fields = false;
public $ready = true;
public array $context = []; public array $context = [];
#[On('update.context')] #[On('update.context')]
@ -70,9 +78,17 @@ class InvoicePay extends Component
} }
#[On('payable-amount')]
public function payableAmount($payable_amount)
{
$this->context['payable_invoices'][0]['amount'] = Number::parseFloat($payable_amount);
$this->under_over_payment = false;
}
#[On('payment-method-selected')] #[On('payment-method-selected')]
public function paymentMethodSelected($company_gateway_id, $gateway_type_id, $amount) public function paymentMethodSelected($company_gateway_id, $gateway_type_id, $amount)
{ {
$this->context['company_gateway_id'] = $company_gateway_id; $this->context['company_gateway_id'] = $company_gateway_id;
$this->context['gateway_type_id'] = $gateway_type_id; $this->context['gateway_type_id'] = $gateway_type_id;
$this->context['amount'] = $amount; $this->context['amount'] = $amount;
@ -83,6 +99,8 @@ class InvoicePay extends Component
// $this->invite = \App\Models\InvoiceInvitation::withTrashed()->find($this->invitation_id)->withoutRelations(); // $this->invite = \App\Models\InvoiceInvitation::withTrashed()->find($this->invitation_id)->withoutRelations();
$this->payment_method_accepted =true; $this->payment_method_accepted =true;
} }
#[Computed()] #[Computed()]
@ -94,10 +112,14 @@ class InvoicePay extends Component
if(!$this->signature_accepted) if(!$this->signature_accepted)
return Signature::class; return Signature::class;
if($this->under_over_payment)
return UnderOverPayment::class;
if(!$this->payment_method_accepted) if(!$this->payment_method_accepted)
return PaymentMethod::class; return PaymentMethod::class;
return ProcessPayment::class; // if($this->ready)
return ProcessPayment::class;
} }
#[Computed()] #[Computed()]
@ -116,13 +138,23 @@ class InvoicePay extends Component
$client = $invite->contact->client; $client = $invite->contact->client;
$variables = ($invite && auth()->guard('contact')->user()->client->getSetting('show_accept_invoice_terms')) ? (new HtmlEngine($invite))->generateLabelsAndValues() : false; $variables = ($invite && auth()->guard('contact')->user()->client->getSetting('show_accept_invoice_terms')) ? (new HtmlEngine($invite))->generateLabelsAndValues() : false;
$settings = $client->getMergedSettings(); $settings = $client->getMergedSettings();
$this->context['settings'] = $settings;
//under-over / payment
//required fields
$this->terms_accepted = !$settings->show_accept_invoice_terms; $this->terms_accepted = !$settings->show_accept_invoice_terms;
$this->signature_accepted = !$settings->require_invoice_signature; $this->signature_accepted = !$settings->require_invoice_signature;
$this->under_over_payment = $settings->client_portal_allow_over_payment || $settings->client_portal_allow_under_payment;
$this->required_fields = false;
$this->context['variables'] = $variables; $this->context['variables'] = $variables;
$this->context['invoice'] = $invite->invoice; $this->context['invoice'] = $invite->invoice;
$this->context['settings'] = $settings; $this->context['settings'] = $settings;
$this->context['payable_invoices'] = ['invoice_id' => $this->context['invoice']->hashed_id, 'amount' => $invite->invoice->partial > 0 ? $invite->invoice->partial : $invite->invoice->balance];
} }
public function render() public function render()

View File

@ -29,6 +29,10 @@
isLoading = false; isLoading = false;
}); });
Livewire.on('singlePaymentMethodFound', (event) => {
$wire.dispatch('payment-method-selected', {company_gateway_id: event.company_gateway_id, gateway_type_id: event.gateway_type_id, amount: event.amount })
});
const buttons = document.querySelectorAll('.payment-method'); const buttons = document.querySelectorAll('.payment-method');
buttons.forEach(button => { buttons.forEach(button => {

View File

@ -0,0 +1,3 @@
<div>
</div>

View File

@ -0,0 +1,37 @@
<div x-data="{ payableAmount: '{{ $payableAmount }}' }" class="px-4 py-5 bg-white sm:gap-4 sm:px-6">
<dt class="text-sm font-medium leading-5 text-gray-500">
{{ ctrans('texts.payment_amount') }}
</dt>
<dd class="text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2 flex flex-col">
<div class="flex items-center">
<label>
<span class="mt-2">{{ $currency->code }} ({{ $currency->symbol }})</span>
<input
type="text"
class="input mt-0 mr-4 relative"
name="payable_amount"
x-model="payableAmount"
value="{{ $payableAmount }}"/>
</label>
</div>
@if($settings->client_portal_allow_under_payment)
<span class="mt-1 text-sm text-gray-800">{{ ctrans('texts.minimum_payment') }}: {{ $settings->client_portal_under_payment_minimum }}</span>
@endif
</dd>
<div class="bg-white px-4 py-5 flex w-full justify-end">
<button
class="button button-primary bg-primary payment-method flex items-center justify-center relative py-4"
@click="$wire.dispatch('payable-amount', { payable_amount: payableAmount })">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ ctrans('texts.next') }}</span>
</button>
</div>
</div>