Improvements for mollie in test mode

This commit is contained in:
David Bomba
2026-01-22 10:45:37 +11:00
parent 08de178c80
commit 5ddbc2ff1f
8 changed files with 145 additions and 26 deletions

View File

@@ -288,11 +288,49 @@ class InvoiceFilters extends QueryFilters
if ($sort_col[0] == 'client_id') {
//2025-12-16: Better filtering for clients.
return $this->builder->orderByRaw('client_id IS NULL')
->orderBy(\App\Models\Client::select('name')
->whereColumn('clients.id', 'invoices.client_id')
->limit(1), $dir);
// 2026-01-21: Original sort by client name that is not optimal when clients.name is empty.
// return $this->builder->orderByRaw('client_id IS NULL')
// ->orderBy(\App\Models\Client::select('name')
// ->whereColumn('clients.id', 'recurring_invoices.client_id')
// ->limit(1), $dir);
/**
* future options for order by raw if this is not performant:
*
COALESCE(
NULLIF((SELECT name FROM clients WHERE clients.id = invoices.client_id LIMIT 1), ''),
(SELECT email FROM client_contacts
WHERE client_contacts.client_id = invoices.client_id
AND client_contacts.email IS NOT NULL
ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC
LIMIT 1),
'No Contact Set'
) " . $dir
*/
return $this->builder
->orderByRaw("
CASE
WHEN CHAR_LENGTH((SELECT name FROM clients WHERE clients.id = invoices.client_id LIMIT 1)) > 1
THEN (SELECT name FROM clients WHERE clients.id = invoices.client_id LIMIT 1)
WHEN CHAR_LENGTH(CONCAT(
COALESCE((SELECT first_name FROM client_contacts WHERE client_contacts.client_id = invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1), ''),
COALESCE((SELECT last_name FROM client_contacts WHERE client_contacts.client_id = invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1), '')
)) >= 1
THEN TRIM(CONCAT(
COALESCE((SELECT first_name FROM client_contacts WHERE client_contacts.client_id = invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1), ''),
' ',
COALESCE((SELECT last_name FROM client_contacts WHERE client_contacts.client_id = invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1), '')
))
WHEN CHAR_LENGTH((SELECT email FROM client_contacts WHERE client_contacts.client_id = invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1)) > 0
THEN (SELECT email FROM client_contacts WHERE client_contacts.client_id = invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1)
ELSE 'No Contact Set'
END " . $dir
);
}
if ($sort_col[0] == 'project_id') {

View File

@@ -142,14 +142,34 @@ class RecurringInvoiceFilters extends QueryFilters
if ($sort_col[0] == 'client_id') {
return $this->builder->orderByRaw('client_id IS NULL')
->orderBy(\App\Models\Client::select('name')
->whereColumn('clients.id', 'recurring_invoices.client_id')
->limit(1), $dir);
// return $this->builder->orderByRaw('ISNULL(client_id), client_id '. $dir)
// ->orderBy(\App\Models\Client::select('name')
// ->whereColumn('clients.id', 'recurring_invoices.client_id'), $dir);
return $this->builder
->orderByRaw("
CASE
WHEN CHAR_LENGTH((SELECT name FROM clients WHERE clients.id = recurring_invoices.client_id LIMIT 1)) > 1
THEN (SELECT name FROM clients WHERE clients.id = recurring_invoices.client_id LIMIT 1)
WHEN CHAR_LENGTH(CONCAT(
COALESCE((SELECT first_name FROM client_contacts WHERE client_contacts.client_id = recurring_invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1), ''),
COALESCE((SELECT last_name FROM client_contacts WHERE client_contacts.client_id = recurring_invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1), '')
)) >= 1
THEN TRIM(CONCAT(
COALESCE((SELECT first_name FROM client_contacts WHERE client_contacts.client_id = recurring_invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1), ''),
' ',
COALESCE((SELECT last_name FROM client_contacts WHERE client_contacts.client_id = recurring_invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1), '')
))
WHEN CHAR_LENGTH((SELECT email FROM client_contacts WHERE client_contacts.client_id = recurring_invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1)) > 0
THEN (SELECT email FROM client_contacts WHERE client_contacts.client_id = recurring_invoices.client_id AND client_contacts.email IS NOT NULL ORDER BY client_contacts.is_primary DESC, client_contacts.id ASC LIMIT 1)
ELSE 'No Contact Set'
END " . $dir
);
// return $this->builder->orderByRaw('client_id IS NULL')
// ->orderBy(\App\Models\Client::select('name')
// ->whereColumn('clients.id', 'recurring_invoices.client_id')
// ->limit(1), $dir);
}
if ($sort_col[0] == 'number') {

View File

@@ -2,19 +2,19 @@
namespace App\PaymentDrivers\Mollie;
use App\Exceptions\PaymentFailed;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\MolliePaymentDriver;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
use App\Models\GatewayType;
use App\Models\PaymentType;
use App\Jobs\Util\SystemLogger;
use App\Exceptions\PaymentFailed;
use App\Models\ClientGatewayToken;
use Illuminate\Http\RedirectResponse;
use Illuminate\Contracts\View\Factory;
use App\PaymentDrivers\MolliePaymentDriver;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
class CreditCard implements LivewireMethodInterface
{
@@ -151,6 +151,7 @@ class CreditCard implements LivewireMethodInterface
$payment = $this->mollie->gateway->payments->create($data);
if ($payment->status === 'paid') {
$this->mollie->logSuccessfulGatewayResponse(
['response' => $payment, 'data' => $this->mollie->payment_hash->data],
SystemLog::TYPE_MOLLIE
@@ -177,6 +178,7 @@ class CreditCard implements LivewireMethodInterface
public function processSuccessfulPayment(\Mollie\Api\Resources\Payment $payment)
{
$payment_hash = $this->mollie->payment_hash;
if (property_exists($payment_hash->data, 'shouldStoreToken') && $payment_hash->data->shouldStoreToken) {
@@ -212,7 +214,7 @@ class CreditCard implements LivewireMethodInterface
'payment_type' => PaymentType::CREDIT_CARD_OTHER,
'transaction_reference' => $payment->id,
];
$payment_record = $this->mollie->createPayment($data, $payment->status === 'paid' ? Payment::STATUS_COMPLETED : Payment::STATUS_PENDING);
SystemLogger::dispatch(

View File

@@ -22,10 +22,12 @@ use App\Models\PaymentType;
use App\Jobs\Util\SystemLogger;
use App\Utils\Traits\MakesHash;
use Mollie\Api\MollieApiClient;
use App\Exceptions\PaymentFailed;
use App\Models\ClientGatewayToken;
use App\PaymentDrivers\BaseDriver;
use App\PaymentDrivers\Mollie\KBC;
use App\PaymentDrivers\Mollie\IDEAL;
use App\Exceptions\PaymentOpenMollie;
use Mollie\Api\Exceptions\ApiException;
use App\PaymentDrivers\Mollie\Bancontact;
use App\PaymentDrivers\Mollie\CreditCard;
@@ -311,8 +313,6 @@ class MolliePaymentDriver extends BaseDriver
'paid' => Payment::STATUS_COMPLETED,
];
nlog($request->id);
try {
$payment = $this->gateway->payments->get($request->id);
$record = Payment::withTrashed()->where('transaction_reference', $request->id)->first();
@@ -320,7 +320,28 @@ class MolliePaymentDriver extends BaseDriver
if ($record) {
$client = $record->client;
$this->client = $client;
} else {
}
elseif($payment->status == 'failed' && $payment->metadata->gateway_type_id === GatewayType::CREDIT_CARD){
//no payment, and it failed? return early!
$client = Client::withTrashed()->find($this->decodePrimaryKey($payment->metadata->client_id));
$message = [
'server_response' => $payment,
'data' => $request->all(),
];
SystemLogger::dispatch(
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_MOLLIE,
$client,
$client->company
);
return response()->json([], 200);
}
else {
$client = Client::withTrashed()->find($this->decodePrimaryKey($payment->metadata->client_id));
$this->client = $client;
// sometimes if the user is not returned to the site with a response from Mollie
@@ -427,6 +448,15 @@ class MolliePaymentDriver extends BaseDriver
try {
$payment = $this->gateway->payments->get($request->getPaymentId());
// if($payment->status == 'open'){
// nlog("open furfy");
// return render('gateways.mollie.mollie_pending_payment_placeholder');
// }
// else
if($payment->status == 'failed'){
return (new CreditCard($this))->processUnsuccessfulPayment(new PaymentFailed($payment->details->failureMessage, 400));
}
return (new CreditCard($this))->processSuccessfulPayment($payment);
} catch (\Mollie\Api\Exceptions\ApiException $e) {

View File

@@ -5690,6 +5690,7 @@ $lang = array(
'peppol_sending_failed' => 'E-Invoice sending failed!',
'peppol_sending_success' => 'E-Invoice sent successfully!',
'auto_generate' => 'Auto Generate',
'mollie_payment_pending' => 'Your payment is pending. Please wait for it to be processed. We will email you when it is completed.',
);
return $lang;

View File

@@ -5688,6 +5688,7 @@ Développe automatiquement la section des notes dans le tableau de produits pour
'purge_user_confirmation' => 'Attention ! Cette action réattribuera toutes les entités au propriétaire du compte et supprimera définitivement l\'utilisateur de l\'ensemble des entreprises et des comptes. Voulez-vous vraiment continuer ?',
'peppol_sending_failed' => 'Problème technique de livraison. Réessai impossible.',
'peppol_sending_success' => 'La facture électronique a été envoyée!',
'auto_generate' => 'Auto générer',
);
return $lang;

View File

@@ -5689,6 +5689,7 @@ $lang = array(
'purge_user_confirmation' => 'Cảnh báo! Thao tác này sẽ gán lại tất cả các thực thể đến chủ sở hữu tài khoản và Xóa vĩnh viễn Người dùng trên tất cả các công ty và tài khoản. Bạn có chắc chắn muốn đến tục không?',
'peppol_sending_failed' => 'Sự cố giao hàng kỹ thuật. Không thể thử lại',
'peppol_sending_success' => 'E- Hóa đơn gửi Thành công !',
'auto_generate' => 'Tự động tạo',
);
return $lang;

View File

@@ -0,0 +1,26 @@
@extends('portal.ninja2020.layout.clean')
@section('meta_title', 'Mollie')
@section('body')
<div class="grid lg:grid-cols-3">
<div class="hidden lg:block col-span-1 bg-red-100 h-screen">
<img src="{{ asset('images/client-portal-new-image.jpg') }}"
class="w-full h-screen object-cover"
alt="Background image">
</div>
<div class="col-span-2 h-screen flex">
<div class="m-auto md:w-1/2 lg:w-1/4 flex flex-col items-center">
<span class="flex items-center text-2xl">
{{ ctrans('texts.mollie_payment_pending') }}
</span>
<a class="button-link text-sm mt-2" href="{{ url(request()->getSchemeAndHttpHost() . '/client') }}">
{{ ctrans('texts.back_to', ['url' => parse_url(request()->getHttpHost())['host'] ?? request()->getHttpHost()]) }}
</a>
</div>
</div>
</div>
@endsection