billing: Nebenläufigkeit & Idempotenz härten (H4, Stripe, Boost-Slots)
- CreditTopup-Gutschrift, MAN-Rechnung, Proof-PDF und Stripe-Webhook- Spiegelung sperren die betroffene Zeile innerhalb der Transaktion und prüfen die Idempotenz erst danach (verhindert Doppelgutschrift bei at-least-once-Webhooks, H4). - Gemeinsamer LocksModelForUpdate-Trait für die häufige Lock-by-Key-Form (CreditTopup, ManualInvoice). - Unique-Index auf invoices.stripe_invoice_id; Boost-Inventar über boost_slot_locks serialisiert, verwaiste Kategorie-Locks werden beim Löschen der Rubrik entfernt. Deployment: vor migrate prüfen, ob invoices.stripe_invoice_id bereits Duplikate enthält (die Unique-Migration bricht sonst bewusst ab). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
3295f47556
commit
aae456954a
14 changed files with 418 additions and 106 deletions
|
|
@ -7,6 +7,7 @@ use App\Models\BillingAddress;
|
|||
use App\Models\Invoice;
|
||||
use App\Models\SinglePurchase;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Laravel\Cashier\Events\WebhookReceived;
|
||||
|
||||
|
|
@ -81,6 +82,17 @@ test('duplicate webhook deliveries do not create a second invoice', function ()
|
|||
expect(Invoice::count())->toBe(1);
|
||||
});
|
||||
|
||||
test('stripe invoice ids are unique in the database while null remains repeatable', function () {
|
||||
Invoice::factory()->create(['stripe_invoice_id' => 'in_database_unique']);
|
||||
|
||||
expect(fn () => Invoice::factory()->create(['stripe_invoice_id' => 'in_database_unique']))
|
||||
->toThrow(QueryException::class);
|
||||
|
||||
Invoice::factory()->count(2)->create(['stripe_invoice_id' => null]);
|
||||
|
||||
expect(Invoice::query()->whereNull('stripe_invoice_id')->count())->toBe(2);
|
||||
});
|
||||
|
||||
test('the snapshot falls back to the local billing address including vat id', function () {
|
||||
$user = User::factory()->create(['stripe_id' => 'cus_test_1']);
|
||||
BillingAddress::factory()->create([
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue