From e2ea2ff9ab3bfc63b917b050ec3d99ad912ce4e4 Mon Sep 17 00:00:00 2001 From: "Fabian @ Blax Software" Date: Wed, 7 Oct 2026 12:57:11 +0200 Subject: [PATCH] fix(ledger): PayPal import survives a concurrent run of itself A manual import overlapping the scheduled one could insert the same PayPal transaction twice and fail on the unique key. The loser now updates the row the other run created. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../PaymentProvider/PaypalLedgerService.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Services/PaymentProvider/PaypalLedgerService.php b/src/Services/PaymentProvider/PaypalLedgerService.php index 2d4e266..d54ff61 100644 --- a/src/Services/PaymentProvider/PaypalLedgerService.php +++ b/src/Services/PaymentProvider/PaypalLedgerService.php @@ -172,7 +172,19 @@ class PaypalLedgerService return 'updated'; } - $model::query()->create($row); + try { + $model::query()->create($row); + } catch (\Illuminate\Database\QueryException $e) { + // A concurrent import (manual run during the scheduled one) inserted + // the same transaction first: update that row instead. + $existing = $model::query()->where('stripe_id', $row['stripe_id'])->first(); + if (! $existing) { + throw $e; + } + $existing->fill($row)->save(); + + return 'updated'; + } return 'created'; }