'DE', 'phone' => '49', 'en' => 'Germany', 'de' => 'Deutschland', 'es' => 'Alemania', 'fr' => 'Allemagne', 'it' => 'Germania', 'ru' => 'Германия', 'eu_country' => true, ]); $account = UserAccount::create([ 'first_name' => 'Klaus', 'last_name' => 'Kunde', 'address' => 'Hauptstrasse 1', 'zipcode' => '10115', 'city' => 'Berlin', 'country_id' => $country->id, ]); $user = User::forceCreate([ 'account_id' => $account->id, 'email' => 'klaus@example.com', 'password' => bcrypt('secret'), 'lang' => 'de', ]); $shoppingUser = ShoppingUser::create([ 'auth_user_id' => $user->id, 'billing_firstname' => 'Klaus', 'billing_lastname' => 'Kunde', 'billing_address' => 'Hauptstrasse 1', 'billing_zipcode' => '10115', 'billing_city' => 'Berlin', 'billing_country_id' => $country->id, 'billing_email' => $user->email, 'same_as_billing' => true, 'shipping_firstname' => 'Klaus', 'shipping_lastname' => 'Kunde', 'shipping_address' => 'Hauptstrasse 1', 'shipping_zipcode' => '10115', 'shipping_city' => 'Berlin', 'shipping_country_id' => $country->id, 'is_for' => 'me', 'is_from' => 'user_order', 'mode' => 'live', ]); $userAbo = UserAbo::create([ 'user_id' => $user->id, 'shopping_user_id' => $shoppingUser->id, 'is_for' => 'me', 'email' => $user->email, 'payone_userid' => 654321, 'clearingtype' => 'cc', 'active' => true, 'status' => 3, // abo_hold (Blockade) 'abo_interval' => 5, 'next_date' => now()->subDays(2), // ueberfaellig ]); $order = ShoppingOrder::create([ 'shopping_user_id' => $shoppingUser->id, 'auth_user_id' => $user->id, 'country_id' => $country->id, 'language' => 'de', 'user_shop_id' => 1, 'payment_for' => 6, 'total' => 50.00, 'subtotal' => 50.00, 'points' => 25, 'paid' => false, 'shipped' => 0, 'is_abo' => true, 'abo_interval' => 5, 'txaction' => 'error', 'mode' => 'live', ]); $aboOrder = UserAboOrder::create([ 'user_abo_id' => $userAbo->id, 'shopping_order_id' => $order->id, 'status' => 3, // abo_hold 'paid' => false, ]); return [$userAbo, $order, $aboOrder, $user]; } it('markiert eine angehaltene Abo-Bestellung als extern erledigt, schreibt Punkte gut und hebt die Blockade auf', function () { [$userAbo, $order, $aboOrder, $user] = heldAboSeed(); // Vorher zaehlt die angehaltene Lieferung nicht als ausgefuehrte Lieferung. expect(UserAbo::find($userAbo->id)->getCountPaidOrders())->toBe(0); $result = app(AboExternalCompletionService::class)->complete($order); expect($result['success'])->toBeTrue(); $order->refresh(); $aboOrder->refresh(); $userAbo->refresh(); // Bestellung bleibt unbezahlt, keine Rechnung expect((bool) $order->paid)->toBeFalse() ->and((int) $order->shipped)->toBe(2) ->and($order->isInvoice())->toBeFalse(); // Abo-Bestellung: gruener Status 8, weiterhin unbezahlt expect((int) $aboOrder->status)->toBe(8) ->and((bool) $aboOrder->paid)->toBeFalse(); // Blockade aufgehoben: zurueck auf okay, aktiv, next_date in der Zukunft expect((int) $userAbo->status)->toBe(2) ->and($userAbo->active)->toBeTrue(); expect(\Carbon\Carbon::parse($userAbo->getRawOriginal('next_date'))->isFuture())->toBeTrue(); // Abo-Lieferungs-Zaehler beruecksichtigt die extern erledigte Ausfuehrung. $fresh = UserAbo::find($userAbo->id); expect($fresh->getCountPaidOrders())->toBe(1) ->and($fresh->getCountOrders())->toBe(1); // Punkte gutgeschrieben - mit heutigem Datum (Markierungsdatum), nicht dem // vergangenen Bestelldatum, damit sie in der laufenden Monatsauswertung landen. $volume = UserSalesVolume::where('shopping_order_id', $order->id)->first(); expect($volume)->not->toBeNull() ->and((float) $volume->points)->toBe(25.0) ->and((int) $volume->user_id)->toBe($user->id) ->and((int) $volume->month)->toBe((int) date('m')) ->and((int) $volume->year)->toBe((int) date('Y')) ->and($volume->date)->toBe(date('d.m.Y')); }); it('trackt Incentive-Punkte mit dem Bestelldatum (Ausfuehrungsmonat), nicht mit heute', function () { \Carbon\Carbon::setTestNow('2026-06-15'); [$userAbo, $order, , $user] = heldAboSeed(); // Die vorgesehene Ausfuehrung lag im April; das Incentive-Fenster deckt nur // April ab (nicht Juni/heute). Wuerde der Tracker "heute" verwenden, faende // er das Incentive nicht und legte keinen IncentiveNewAbo-Eintrag an. $executionDate = \Carbon\Carbon::parse('2026-04-10'); ShoppingOrder::where('id', $order->id)->update(['created_at' => $executionDate]); Incentive::factory()->active()->create([ 'qualification_start' => '2026-04-01', 'qualification_end' => '2026-04-30', 'calculation_end' => '2026-05-31', ]); app(AboExternalCompletionService::class)->complete($order->fresh()); // Incentive-Abo wurde dem April-Fenster zugeordnet, activated_at = Bestelldatum. $newAbo = IncentiveNewAbo::where('user_abo_id', $userAbo->id)->first(); expect($newAbo)->not->toBeNull() ->and($newAbo->activated_at->toDateString())->toBe('2026-04-10'); // Incentive-Zaehler (qualified_abos) des Teilnehmers wurde erhoeht. $participant = \App\Models\IncentiveParticipant::find($newAbo->participant_id); expect((int) $participant->qualified_abos)->toBe(1); // Reguläre Provisionspunkte hingegen mit heutigem Datum (Juni). $volume = UserSalesVolume::where('shopping_order_id', $order->id)->first(); expect((int) $volume->month)->toBe(6) ->and((int) $volume->year)->toBe(2026); \Carbon\Carbon::setTestNow(); }); it('ist idempotent und schreibt Punkte nicht doppelt gut', function () { [, $order] = heldAboSeed(); $service = app(AboExternalCompletionService::class); $first = $service->complete($order); $second = $service->complete($order->fresh()); expect($first['success'])->toBeTrue() ->and($second['success'])->toBeFalse(); expect(UserSalesVolume::where('shopping_order_id', $order->id)->count())->toBe(1); }); it('verweigert die Aktion fuer eine bereits bezahlte Abo-Bestellung', function () { [, $order, $aboOrder] = heldAboSeed(); $aboOrder->update(['paid' => true]); $result = app(AboExternalCompletionService::class)->complete($order->fresh()); expect($result['success'])->toBeFalse(); expect(UserSalesVolume::where('shopping_order_id', $order->id)->exists())->toBeFalse(); }); it('verweigert die Aktion fuer eine Nicht-Abo-Bestellung', function () { [, $order] = heldAboSeed(); $order->update(['is_abo' => false]); $result = app(AboExternalCompletionService::class)->complete($order->fresh()); expect($result['success'])->toBeFalse(); }); it('erledigt ueber die Abo-Detailseite die juengste angehaltene Bestellung', function () { [$userAbo, $order] = heldAboSeed(); $result = app(AboExternalCompletionService::class)->completeForAbo($userAbo); expect($result['success'])->toBeTrue(); expect((int) UserAboOrder::where('shopping_order_id', $order->id)->value('status'))->toBe(8); expect((int) $userAbo->fresh()->status)->toBe(2); });